我试图从图库中获取照片以将其发送到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
和异常:
由于未捕获的异常终止应用程序' NSInvalidArgumentException',原因:' *** - [__ NSDictionaryM setObject:forKey:]:key不能为nil'
我在模拟器iPhone SE(11.2 Xcode 9.2)中运行应用程序。 Project min iOS版本是8.2。 UIImagePickerController
在NavigationViewController
中调用了public abstract class Armor
{
public abstract void Equip( MainCharacterEquipment mce );
}
public class HeadArmor : Armor
{
public override void Equip( MainCharacterEquipment mce )
{
mce.HeadSlot=this;
}
}
public class ChestArmor : Armor
{
public override void Equip( MainCharacterEquipment mce )
{
mce.ChestSlot=this;
}
}
。
如何解决这个问题?
答案 0 :(得分:1)
你崩溃的原因是这一行:
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()
}
现在想想那些行将执行的 order 。 requestAuthorization
是异步。因此执行顺序如下:
func checkPhotoAccess() -> Bool {
PHPhotoLibrary.requestAuthorization({status in
return // 2
})
return checkPhotoAccess() // 1
}
好的,但是2
永远不会执行,因为1
首先返回。所以我们留下了这个:
func checkPhotoAccess() -> Bool {
return checkPhotoAccess()
}
但这显然是疯了。我们有一个无限的递归。
需要注意的是无法从checkPhotoAccess
返回值,因为您需要调用异步的requestAuthorization
。实现此类事情的正确方法是在false
情况下返回.notDetermined
,否则(更好)编写接收完成函数<的<{1}}方法/ em>然后,如果发现我们有授权,则可以调用该函数。
此外,您需要立即停止使用UIAlertView并转换为UIAlertController。 UIAlertView已被弃用 long 之前。编译器会警告你这个,所以请听听它告诉你的内容!