Determine if the access to photo library is set or not - PHPhotoLibrary
Check +[PHPhotoLibrary authorizationStatus]
– if not set, it will return PHAuthorizationStatusNotDetermined
. (You can then request access using +requestAuthorization:
on the same class.)
check for authorization status to photo library
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
The docs for ALAuthorizationStatus
show the possible values. This API only works under iOS 6.0 or later.
Swift how to show alert to request permission for photo library?
If the status be on . notDetermined
, so the app automatically shows the alert to the user, but if the status was on .restricted
or denied
you cannot do anything to ask user again for the access to the photos like the original one, but you can make a custom alert and ask user to give you access to the photos and if user accepted your request, lead the user to the setting and ask him to enable your access manually!
iOS11 photo library access is possible even if settings are set to never
Okay, you can sort of piece this together from answers and comments already, but to try to tell a more complete story...
In iOS 11, UIImagePickerController
runs as a separate process from your app. That means:
- Your app can't see the user's whole Photos library — it gets read-only access just for whichever asset(s) the user chooses in the image picker.
- Because of (1), your app doesn't need the standard privacy authorization for Photos library access. The user explicitly chooses a specific asset (or multiple) for use in your app, which means the user is granting your app permission to read the asset(s) in question.
You can see more about this in the WWDC17 talk on PhotoKit.
(By the way, this model matches what you've seen in the Contacts framework since iOS 9; if you show contact picker, your app only gets a one-time drop of contact information for the contact(s) the user picked, not ongoing read/write access to the Contacts database, so the contact picker doesn't require special privacy permission.)
PHPhotoLibrary
and its authorization status reflect the global read/write permission for Photos access that users can control from Settings > Privacy. (That's the one where your Info.plist needs NSPhotoLibraryUsageDescription
.) Any use of the PHPhotoLibrary
API requires this permission, regardless of whether your app's use of that API is only for writing or only for reading. This has been true since PhotoKit was introduced in iOS 8.
If you're not using PHPhotoLibrary
, PHAsset
, etc, there are narrower permission options that are new in iOS 11 (and not part of the Photos.framework API):
- As noted above,
UIImagePickerController
doesn't need blanket Privacy Settings permission because each use grants one-time read access for the specific assets chosen. If you need only to add new assets to the Photos library, use
UIImageWriteToSavedPhotosAlbum
orUISaveVideoAtPathToSavedPhotosAlbum
. With those you can putNSPhotoLibraryAddUsageDescription
in your Info.plist — then the system's Privacy Settings will make clear to the user that they're not giving your permission to see or modify existing assets, only to add new ones.If the user grants add-only permission, it applies only to those UIKit functions — attempting to use
PHPhotoLibrary
will still prompt for (and require the Info.plist key for) read/write access.See this part of the WWDC17 talk for more on the add-only privacy setting.
In Swift 4.1 how do you request write-only permission for the photo library?
Unfortunately, access control for PhotoKit
is not separated between read and write. If you look at PHAuthorizationStatus, there are only cases where full access is granted. No write only option.
NSPhotoLibraryUsageDescription
is the only privacy message you can configure, so you can let the user know that you are only writing, not reading. App store review will make sure that is true.
Edit: also see Detect add photos only permission for iOS 11+
Image gallery not show after request access permission
The way that UICollectionView.rx.items
works is that it observes its dataSource. When the dataSource emits a new array, the items operator will reload the collection view and call its closure for each item.
Since you are using just
as your data source, only one array is emitted and the collection view never changes. You have to tie the source to the change observer to get it to work. Here is a working example:
extension PhotosViewController { // a UICollectionViewController
func connect(disposeBag: DisposeBag) {
// initial fetch result
let allPhotosOptions = PHFetchOptions()
allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
let initialFetchResult = PHAsset.fetchAssets(with: allPhotosOptions)
let assets = PHPhotoLibrary.shared().rx.registerChangeObserver()
// when a change is observed, we need to update the fetchResult
.scan(initialFetchResult) { oldResult, change in
guard let changes = change.changeDetails(for: oldResult) else { return oldResult }
return changes.fetchResultAfterChanges
}
// but first send the initial asset fetch to the collection view
.startWith(initialFetchResult)
// and get the assets out of the fetch result.
.map { $0.objects(at: IndexSet(0 ..< $0.count)) }
collectionView.dataSource = nil
assets
.observe(on: MainScheduler.instance)
.bind(to: collectionView.rx.items(cellIdentifier: "GridViewCell", cellType: GridViewCell.self)) { _, asset, cell in
cell.configure(asset: asset)
}
.disposed(by: disposeBag)
}
}
extension Reactive where Base: PHPhotoLibrary {
// not actually needed, but I provided it as an example.
static func requestAuthorization() -> Observable {
Observable.create { observer in
Base.requestAuthorization { status in
observer.onNext(status)
observer.onCompleted()
}
return Disposables.create()
}
}
// this sets up the change observer. Note, your VC isn't the observer.
func registerChangeObserver() -> Observable {
Observable.create { [base] observer in
let changeObserver: RxPhotoLibraryChangeObserver = .init(observer: observer)
base.register(changeObserver)
return Disposables.create { base.unregisterChangeObserver(changeObserver) }
}
}
}
// this is the change observer used in the above.
final class RxPhotoLibraryChangeObserver: NSObject, PHPhotoLibraryChangeObserver {
let observer: AnyObserver
init(observer: AnyObserver) {
self.observer = observer
}
func photoLibraryDidChange(_ changeInstance: PHChange) {
observer.onNext(changeInstance)
}
}
Related Topics
Use Multiple Font Colors in a Single Label
How to Resize Uiview by Dragging from Its Edges
Swift 2: Call Can Throw, But It Is Not Marked with 'Try' and the Error Is Not Handled
Tabbaritems and Setting Their Image Sizes
How to Rotate Text for Uibutton and Uilabel in Swift
How to Create an Umbrella Framework in iOS Sdk
How to Detect When Keyboard Is Shown and Hidden
iPhone Sdk Cgaffinetransform Getting the Angle of Rotation of an Object
Round Top Corners of a Uibutton in Swift
How to Reset the Privacy Settings in iOS
Invalid Swift Support/Invalid Implementation of Swift
Swiftui Navigationview Navigationbartitle Layoutconstraints Issue
How to Detect If a Video File Was Recorded in Portrait Orientation, or Landscape in iOS
Xcode 6.1 Missing Required Architecture X86_64 in File
How to Create Layout Constraints Programmatically
One Step Affine Transform for Rotation Around a Point
Kcfstreamerrordomainssl, -9802 When Connecting to a Server by Ip Address Through Https in iOS 9