Skip to content

Fixes for App Store submission warning - "ITMS-90683: Missing Purpose String in Info.plist" #188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gallery.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "Gallery"
s.summary = "Something good about gallery"
s.version = "2.4.0"
s.version = "2.5.0"
s.homepage = "https://github.com/hyperoslo/Gallery"
s.license = 'MIT'
s.author = { "Hyper Interaktiv AS" => "[email protected]" }
Expand Down
24 changes: 20 additions & 4 deletions Gallery.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,11 @@
3605647F25837D3F00B9F493 /* Permission.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3605644A25837D3F00B9F493 /* Permission.swift */; };
3605648025837D3F00B9F493 /* PermissionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3605644B25837D3F00B9F493 /* PermissionView.swift */; };
3605648125837D3F00B9F493 /* PermissionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3605644C25837D3F00B9F493 /* PermissionController.swift */; };
3605648225837D3F00B9F493 /* LocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3605644D25837D3F00B9F493 /* LocationManager.swift */; };
3605648325837D3F00B9F493 /* PagesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3605644F25837D3F00B9F493 /* PagesController.swift */; };
3605648425837D3F00B9F493 /* PageIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3605645025837D3F00B9F493 /* PageIndicator.swift */; };
5346BEF825DC00D7008494CE /* LocationProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5346BEF425DC00D7008494CE /* LocationProviding.swift */; };
5346BEFA25DC00D7008494CE /* LocationManaging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5346BEF625DC00D7008494CE /* LocationManaging.swift */; };
5346BEFB25DC00D7008494CE /* LocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5346BEF725DC00D7008494CE /* LocationManager.swift */; };
D27B72ED1D6EEEC80093318F /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27B72EC1D6EEEC80093318F /* Tests.swift */; };
D2D1A6F41F84F4DB0083D4C5 /* GalleryController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D1A6C31F84F4DB0083D4C5 /* GalleryController.swift */; };
D5B2E8AA1C3A780C00C0327D /* Gallery.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5B2E89F1C3A780C00C0327D /* Gallery.framework */; };
Expand Down Expand Up @@ -124,9 +126,11 @@
3605644A25837D3F00B9F493 /* Permission.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Permission.swift; sourceTree = "<group>"; };
3605644B25837D3F00B9F493 /* PermissionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PermissionView.swift; sourceTree = "<group>"; };
3605644C25837D3F00B9F493 /* PermissionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PermissionController.swift; sourceTree = "<group>"; };
3605644D25837D3F00B9F493 /* LocationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationManager.swift; sourceTree = "<group>"; };
3605644F25837D3F00B9F493 /* PagesController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagesController.swift; sourceTree = "<group>"; };
3605645025837D3F00B9F493 /* PageIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PageIndicator.swift; sourceTree = "<group>"; };
5346BEF425DC00D7008494CE /* LocationProviding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationProviding.swift; sourceTree = "<group>"; };
5346BEF625DC00D7008494CE /* LocationManaging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationManaging.swift; sourceTree = "<group>"; };
5346BEF725DC00D7008494CE /* LocationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationManager.swift; sourceTree = "<group>"; };
D27B72EC1D6EEEC80093318F /* Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = "<group>"; };
D27B730C1D6EF04D0093318F /* Cartography.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cartography.framework; path = Carthage/Build/iOS/Cartography.framework; sourceTree = "<group>"; };
D2D1A6C31F84F4DB0083D4C5 /* GalleryController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GalleryController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -228,8 +232,8 @@
3605644625837D3F00B9F493 /* Fetcher.swift */,
3605644725837D3F00B9F493 /* Utils.swift */,
3605644825837D3F00B9F493 /* OrientationMan.swift */,
5346BEF325DC00D7008494CE /* Location */,
3605644925837D3F00B9F493 /* Permission */,
3605644D25837D3F00B9F493 /* LocationManager.swift */,
3605644E25837D3F00B9F493 /* Pages */,
);
path = Utils;
Expand Down Expand Up @@ -299,6 +303,16 @@
path = Pages;
sourceTree = "<group>";
};
5346BEF325DC00D7008494CE /* Location */ = {
isa = PBXGroup;
children = (
5346BEF425DC00D7008494CE /* LocationProviding.swift */,
5346BEF625DC00D7008494CE /* LocationManaging.swift */,
5346BEF725DC00D7008494CE /* LocationManager.swift */,
);
path = Location;
sourceTree = "<group>";
};
D27B730E1D6EF0640093318F /* Frameworks */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -481,9 +495,9 @@
files = (
3605647B25837D3F00B9F493 /* GridView.swift in Sources */,
3605647C25837D3F00B9F493 /* Fetcher.swift in Sources */,
3605648225837D3F00B9F493 /* LocationManager.swift in Sources */,
3605646725837D3F00B9F493 /* DropdownController.swift in Sources */,
3605648425837D3F00B9F493 /* PageIndicator.swift in Sources */,
5346BEF825DC00D7008494CE /* LocationProviding.swift in Sources */,
3605648025837D3F00B9F493 /* PermissionView.swift in Sources */,
3605647725837D3F00B9F493 /* EmptyView.swift in Sources */,
3605646B25837D3F00B9F493 /* VideoEditor.swift in Sources */,
Expand Down Expand Up @@ -519,6 +533,7 @@
3605647125837D3F00B9F493 /* UIImageView+Extensions.swift in Sources */,
3605646225837D3F00B9F493 /* ImageCell.swift in Sources */,
3605645425837D3F00B9F493 /* VideoBox.swift in Sources */,
5346BEFA25DC00D7008494CE /* LocationManaging.swift in Sources */,
3605646125837D3F00B9F493 /* Cart.swift in Sources */,
3605646525837D3F00B9F493 /* UIBlurEffect+Style.swift in Sources */,
3605648325837D3F00B9F493 /* PagesController.swift in Sources */,
Expand All @@ -528,6 +543,7 @@
3605647925837D3F00B9F493 /* AlbumCell.swift in Sources */,
3605647A25837D3F00B9F493 /* ArrowButton.swift in Sources */,
3605645A25837D3F00B9F493 /* CameraMan.swift in Sources */,
5346BEFB25DC00D7008494CE /* LocationManager.swift in Sources */,
3605645825837D3F00B9F493 /* CameraController.swift in Sources */,
3605645225837D3F00B9F493 /* VideosLibrary.swift in Sources */,
3605647625837D3F00B9F493 /* UIScrollView+Extensions.swift in Sources */,
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,22 @@ The delegate methods give you `Image` and `Video`, which are just wrappers aroun

`Gallery` handles permissions for you. It checks and askes for photo and camera usage permissions at first launch. As of iOS 10, we need to explicitly declare usage descriptions in plist files

### Madatory
```xml
<key>NSCameraUsageDescription</key>
<string>This app requires access to camera</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app requires access to photo library</string>
```

### Optional
If defining the `GALLERY_USE_LOCATION` compiler flag for the purposes of recording location information then the following usage string is required:

```xml
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app requires location when in use</string>
```

### Configuration

There are lots of customization points in `Config` structs. For example
Expand All @@ -82,6 +91,20 @@ Config.Camera.recordLocation = true
Config.tabsToShow = [.imageTab, .cameraTab]
```

Note: When utilising the `recordLocation` property, `GALLERY_USE_LOCATION` needs defining first in order to expose this functionality. If using Cocoapods this can be done with the usage of post install hook as follows:

```ruby
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'Gallery'
target.build_configurations.each do |config|
config.build_settings['OTHER_SWIFT_FLAGS'] = '-DGALLERY_USE_LOCATION'
end
end
end
end
```

### Video Editor

`Gallery` cares more about video with its editing functionalities. We have `VideoEditor` and `AdvancedVideoEditor` to trim, resize, scale and define quality of the selected video
Expand Down
7 changes: 5 additions & 2 deletions Sources/Gallery/Camera/CameraController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import AVFoundation

class CameraController: UIViewController {

var locationManager: LocationManager?
var locationManager: LocationManaging?
lazy var cameraMan: CameraMan = self.makeCameraMan()
lazy var cameraView: CameraView = self.makeCameraView()
let once = Once()
Expand Down Expand Up @@ -68,9 +68,11 @@ class CameraController: UIViewController {
}

func setupLocation() {
#if GALLERY_USE_LOCATION
if Config.Camera.recordLocation {
locationManager = LocationManager()
}
#endif
}

// MARK: - Action
Expand Down Expand Up @@ -117,7 +119,8 @@ class CameraController: UIViewController {
})

self.cameraView.stackView.startLoading()
cameraMan.takePhoto(previewLayer, location: locationManager?.latestLocation) { [weak self] asset in

self.cameraMan.takePhoto(previewLayer, locationProvider: locationManager?.latestLocationProvider) { [weak self] asset in
guard let strongSelf = self else {
return
}
Expand Down
14 changes: 7 additions & 7 deletions Sources/Gallery/Camera/CameraMan.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ class CameraMan {
let session = AVCaptureSession()
let queue = DispatchQueue(label: "no.hyper.Gallery.Camera.SessionQueue", qos: .background)
let savingQueue = DispatchQueue(label: "no.hyper.Gallery.Camera.SavingQueue", qos: .background)
let orientationMan = OrientationMan()

var backCamera: AVCaptureDeviceInput?
var frontCamera: AVCaptureDeviceInput?
Expand Down Expand Up @@ -127,11 +126,10 @@ class CameraMan {
}
}

func takePhoto(_ previewLayer: AVCaptureVideoPreviewLayer, location: CLLocation?, completion: @escaping ((PHAsset?) -> Void)) {
func takePhoto(_ previewLayer: AVCaptureVideoPreviewLayer, locationProvider: LocationProviding?, completion: @escaping ((PHAsset?) -> Void)) {
guard let connection = stillImageOutput?.connection(with: .video) else { return }

// It should be set the image orientation with the device current orientation
connection.videoOrientation = self.orientationMan.videoOrientation()
connection.videoOrientation = Utils.videoOrientation()

queue.async {
self.stillImageOutput?.captureStillImageAsynchronously(from: connection) {
Expand All @@ -147,12 +145,12 @@ class CameraMan {
return
}

self.savePhoto(image, location: location, completion: completion)
self.savePhoto(image, locationProvider: locationProvider, completion: completion)
}
}
}

func savePhoto(_ image: UIImage, location: CLLocation?, completion: @escaping ((PHAsset?) -> Void)) {
func savePhoto(_ image: UIImage, locationProvider: LocationProviding?, completion: @escaping ((PHAsset?) -> Void)) {
var localIdentifier: String?

savingQueue.async {
Expand All @@ -162,7 +160,9 @@ class CameraMan {
localIdentifier = request.placeholderForCreatedAsset?.localIdentifier

request.creationDate = Date()
request.location = location
#if GALLERY_USE_LOCATION
request.location = locationProvider?.location
#endif
}

DispatchQueue.main.async {
Expand Down
2 changes: 2 additions & 0 deletions Sources/Gallery/Utils/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ public struct Config {

public struct Camera {

#if GALLERY_USE_LOCATION
public static var recordLocation: Bool = false
#endif

public struct ShutterButton {
public static var numberColor: UIColor = UIColor(red: 54/255, green: 56/255, blue: 62/255, alpha: 1)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#if GALLERY_USE_LOCATION
import Foundation
import CoreLocation

class LocationManager: NSObject, CLLocationManagerDelegate {
class LocationManager: NSObject, LocationManaging, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
var latestLocation: CLLocation?
var latestLocationProvider: LocationProviding?

override init() {
super.init()
Expand All @@ -24,7 +25,9 @@ class LocationManager: NSObject, CLLocationManagerDelegate {

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// Pick the location with best (= smallest value) horizontal accuracy
latestLocation = locations.sorted { $0.horizontalAccuracy < $1.horizontalAccuracy }.first
if let location = locations.sorted { $0.horizontalAccuracy < $1.horizontalAccuracy }.first {
latestLocationProvider = LocationProvider(location: location)
}
}

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
Expand All @@ -35,3 +38,5 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
}
}
}

#endif
6 changes: 6 additions & 0 deletions Sources/Gallery/Utils/Location/LocationManaging.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
protocol LocationManaging {

func start()
func stop()
var latestLocationProvider: LocationProviding? { get }
}
15 changes: 15 additions & 0 deletions Sources/Gallery/Utils/Location/LocationProviding.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#if GALLERY_USE_LOCATION
import CoreLocation
#endif

protocol LocationProviding {
#if GALLERY_USE_LOCATION
var location: CLLocation { get }
#endif
}

struct LocationProvider: LocationProviding {
#if GALLERY_USE_LOCATION
let location: CLLocation
#endif
}