调用 UIImagePickerController 提供黑屏
Calling UIImagePickerController provides black screen
我正在尝试从图库中获取照片以将其发送到 api。当我调用 AttachNewFileClick()
时,出现黑屏。
@IBAction func AttachNewFileClick(_ sender: Any) {
if checkPhotoAccess()==true {
let imagePicker = UIImagePickerController(rootViewController: self)
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
present(imagePicker, animated: true, completion: nil)
}
}
func checkPhotoAccess() -> Bool {
let status:PHAuthorizationStatus = PHPhotoLibrary.authorizationStatus();
switch status {
case PHAuthorizationStatus.notDetermined:
PHPhotoLibrary.requestAuthorization({status in
return
})
return checkPhotoAccess()
case .denied:
return false
case .restricted:
let permissionRequestAlert:UIAlertView = UIAlertView(title: "Доступ к галлерее заблокирован", message: "Приложение не может получить доступ к вашей галлерее для прикрепления фото. Вероятно ранее вы заблокировали эту возможность", delegate: self, cancelButtonTitle: "Отмена", otherButtonTitles: "Открыть настройки")
permissionRequestAlert.tag = PERMISSION_REQUEST_ALERT_TAG
permissionRequestAlert.show()
return false
case .authorized:
return true
}
}
然后我给所有的异常添加了断点,并在抛出异常之前高亮了这段代码
libobjc.A.dylib`objc_exception_throw:
-> 0x1159b0f11 <+0>: pushq %rbp
和日志中的异常:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSDictionaryM setObject:forKey:]: key cannot be nil'
我 运行 模拟器中的应用 iPhone SE (11.2 Xcode 9.2)。项目最低 iOS 版本为 8.2。 UIImagePickerController
在模态显示的 NavigationViewController
中被调用。
如何解决这个问题?
您崩溃的原因是这一行:
let imagePicker = UIImagePickerController(rootViewController: self)
这不是您创建 UIImagePickerController 的方式。只需创建它!它已经有了自己的根视图控制器;不要试图改变它。就说:
let imagePicker = UIImagePickerController()
此外,您的 checkPhotoAccess
代码存在致命缺陷:
func checkPhotoAccess() -> Bool {
let status:PHAuthorizationStatus = PHPhotoLibrary.authorizationStatus();
switch status {
case PHAuthorizationStatus.notDetermined:
PHPhotoLibrary.requestAuthorization({status in
return
})
return checkPhotoAccess()
case .denied:
return false
case .restricted:
let permissionRequestAlert:UIAlertView = UIAlertView(title: "Доступ к галлерее заблокирован", message: "Приложение не может получить доступ к вашей галлерее для прикрепления фото. Вероятно ранее вы заблокировали эту возможность", delegate: self, cancelButtonTitle: "Отмена", otherButtonTitles: "Открыть настройки")
permissionRequestAlert.tag = PERMISSION_REQUEST_ALERT_TAG
permissionRequestAlert.show()
return false
case .authorized:
return true
}
}
为了了解原因,让我们排除除 notDetermined
情况之外的所有内容:
func checkPhotoAccess() -> Bool {
PHPhotoLibrary.requestAuthorization({status in
return
})
return checkPhotoAccess()
}
现在考虑执行这些行的顺序。 requestAuthorization
是 异步的 。因此执行顺序是这样的:
func checkPhotoAccess() -> Bool {
PHPhotoLibrary.requestAuthorization({status in
return // 2
})
return checkPhotoAccess() // 1
}
好的,但是 2
将 永远不会 执行,因为 1
return 是第一个。所以我们剩下这个:
func checkPhotoAccess() -> Bool {
return checkPhotoAccess()
}
但这显然是疯了。我们有一个无限递归。
要点是您不能 return 来自checkPhotoAccess
的值,因为您需要调用异步的requestAuthorization
。实现这种事情的正确方法是 return false
在 .notDetermined
情况下,或者(更好)编写一个 checkPhotoAccess
方法来接收 完成函数,如果它发现我们有授权,然后可以调用那个函数。
另外你需要立即停止使用 UIAlertView 并转换为 UIAlertController。 UIAlertView 已在 long 前弃用。编译器会就此警告您,所以请听听它告诉您的内容!
我正在尝试从图库中获取照片以将其发送到 api。当我调用 AttachNewFileClick()
时,出现黑屏。
@IBAction func AttachNewFileClick(_ sender: Any) {
if checkPhotoAccess()==true {
let imagePicker = UIImagePickerController(rootViewController: self)
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
present(imagePicker, animated: true, completion: nil)
}
}
func checkPhotoAccess() -> Bool {
let status:PHAuthorizationStatus = PHPhotoLibrary.authorizationStatus();
switch status {
case PHAuthorizationStatus.notDetermined:
PHPhotoLibrary.requestAuthorization({status in
return
})
return checkPhotoAccess()
case .denied:
return false
case .restricted:
let permissionRequestAlert:UIAlertView = UIAlertView(title: "Доступ к галлерее заблокирован", message: "Приложение не может получить доступ к вашей галлерее для прикрепления фото. Вероятно ранее вы заблокировали эту возможность", delegate: self, cancelButtonTitle: "Отмена", otherButtonTitles: "Открыть настройки")
permissionRequestAlert.tag = PERMISSION_REQUEST_ALERT_TAG
permissionRequestAlert.show()
return false
case .authorized:
return true
}
}
然后我给所有的异常添加了断点,并在抛出异常之前高亮了这段代码
libobjc.A.dylib`objc_exception_throw: -> 0x1159b0f11 <+0>: pushq %rbp
和日志中的异常:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSDictionaryM setObject:forKey:]: key cannot be nil'
我 运行 模拟器中的应用 iPhone SE (11.2 Xcode 9.2)。项目最低 iOS 版本为 8.2。 UIImagePickerController
在模态显示的 NavigationViewController
中被调用。
如何解决这个问题?
您崩溃的原因是这一行:
let imagePicker = UIImagePickerController(rootViewController: self)
这不是您创建 UIImagePickerController 的方式。只需创建它!它已经有了自己的根视图控制器;不要试图改变它。就说:
let imagePicker = UIImagePickerController()
此外,您的 checkPhotoAccess
代码存在致命缺陷:
func checkPhotoAccess() -> Bool {
let status:PHAuthorizationStatus = PHPhotoLibrary.authorizationStatus();
switch status {
case PHAuthorizationStatus.notDetermined:
PHPhotoLibrary.requestAuthorization({status in
return
})
return checkPhotoAccess()
case .denied:
return false
case .restricted:
let permissionRequestAlert:UIAlertView = UIAlertView(title: "Доступ к галлерее заблокирован", message: "Приложение не может получить доступ к вашей галлерее для прикрепления фото. Вероятно ранее вы заблокировали эту возможность", delegate: self, cancelButtonTitle: "Отмена", otherButtonTitles: "Открыть настройки")
permissionRequestAlert.tag = PERMISSION_REQUEST_ALERT_TAG
permissionRequestAlert.show()
return false
case .authorized:
return true
}
}
为了了解原因,让我们排除除 notDetermined
情况之外的所有内容:
func checkPhotoAccess() -> Bool {
PHPhotoLibrary.requestAuthorization({status in
return
})
return checkPhotoAccess()
}
现在考虑执行这些行的顺序。 requestAuthorization
是 异步的 。因此执行顺序是这样的:
func checkPhotoAccess() -> Bool {
PHPhotoLibrary.requestAuthorization({status in
return // 2
})
return checkPhotoAccess() // 1
}
好的,但是 2
将 永远不会 执行,因为 1
return 是第一个。所以我们剩下这个:
func checkPhotoAccess() -> Bool {
return checkPhotoAccess()
}
但这显然是疯了。我们有一个无限递归。
要点是您不能 return 来自checkPhotoAccess
的值,因为您需要调用异步的requestAuthorization
。实现这种事情的正确方法是 return false
在 .notDetermined
情况下,或者(更好)编写一个 checkPhotoAccess
方法来接收 完成函数,如果它发现我们有授权,然后可以调用那个函数。
另外你需要立即停止使用 UIAlertView 并转换为 UIAlertController。 UIAlertView 已在 long 前弃用。编译器会就此警告您,所以请听听它告诉您的内容!