iOS 11权限更新

最近项目中遇到了一个崩溃,当点击图片选择保存的时候,并没有出现请求相册权限的对话框,而是直接就崩溃,并且没有任何错误信息。开始以为是权限没有添加,但是 NSPhotoLibraryUsageDescription 是添加了的,搞不懂了。去翻了翻官方的文档,果然找到了解决方式。

从 iOS 11 开始,相册的权限参数发生了变化,适配 iOS 11 还需要添加一个 NSPhotoLibraryAddUsageDescription 的参数。官方的描述如下:

NSPhotoLibraryAddUsageDescription

NSPhotoLibraryAddUsageDescription ( String - iOS) This key lets you describe the reason your app seeks write-only access to the user’s photo library. When the system prompts the user to allow access, this string is displayed as part of the alert.

Important: To protect user privacy, an iOS app linked on or after iOS 10.0, and that accesses the user’s photo library, must statically declare the intent to do so. Include the NSPhotoLibraryAddUsageDescription key (in apps that link on or after iOS 11) or NSPhotoLibraryUsageDescription key in your app’s Info.plist file and provide a purpose string for the key. If your app attempts to access the user’s photo library without a corresponding purpose string, your app exits.

This key is supported in iOS 11.0 and later.

从 important 的最后一句话可以看出,当应用试图访问用户相册但是 Info.plist 中并没有对应权限的参数的话,应用就会退出。

原因找到,添加上新的参数。搞定!!!

关于 Info.plist 中的 key ,可以参考官方的文档:Cocoa Keys

相关权限申请:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
struct PermissionsManager {

/// 相册权限
///
/// - Parameters:
/// - authorizedClosure: 已授权回调
/// - deniedClosure: 未授权回调
static func albumPermissions(authorizedClosure: (() -> ())?, deniedClosure: (() -> ())?) {

let status = PHPhotoLibrary.authorizationStatus()

switch status {
case .notDetermined:
PHPhotoLibrary.requestAuthorization { _ in
self.albumPermissions(authorizedClosure: authorizedClosure, deniedClosure: deniedClosure)
}
case .authorized:
if let authorized = authorizedClosure {
authorized()
}
default:
if let denied = deniedClosure {
denied()
}
}
}


/// 相机权限
///
/// - Parameters:
/// - authorizedClosure: 已授权回调
/// - deniedClosure: 未授权回调
static func cameraPermissions(authorizedClosure: (() -> ())?, deniedClosure: (() -> ())?) {

let status = AVCaptureDevice.authorizationStatus(for: .video)

switch status {
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { _ in
self.cameraPermissions(authorizedClosure: authorizedClosure, deniedClosure: deniedClosure)
}
case .authorized:
if let authorized = authorizedClosure {
authorized()
}
default:
if let denied = deniedClosure {
denied()
}
}
}
}