(Swift) UIImagePickerController照片选择器UIImagePickerControllerReferenceURL的问题
今天在定位一个照片选择奔溃闪退的问题,真机测试所有iPhone运行正常,ipad测试中使用ipad Air ios8的时候总算问题复现了。下面我总结一下自己测试一天才测试出来的bug。
现象:点击个人主页头像,进行照片选择,点击照片,应用程序闪退。
iOS 获取图片有三种方法:
1. 直接调用摄像头拍照
2. 从相册中选择
3. 从图库中选择
UIImagePickerControllerSourceTypePhotoLibrary:表示显示所有的照片
UIImagePickerControllerSourceTypeCamera:表示从摄像头选取照片
UIImagePickerControllerSourceTypeSavedPhotosAlbum:表示仅仅从相册中选取照片。
allowEditing和allowsImageEditing 设置为YES,表示 允许用户编辑图片,否则,不允许用户编辑。
代码如下:
1 @IBAction func onCoverClick(sender: AnyObject) { 2 if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.SavedPhotosAlbum)) { 3 self.coverChanging = true 4 5 let actionSheet = UIActionSheet( title: Localized.PHOTO_CHOSE_SOURCE, delegate: self, cancelButtonTitle:Localized.DIALOG_BUTTON_CANCEL , destructiveButtonTitle: nil, otherButtonTitles: Localized.PHOTO_FROM_CAMERA, Localized.PHOTO_FROM_PHOTO ) 6 actionSheet.showInView(self.view) 7 } 8 }
//MARK: - uiactionsheetDelegate func actionSheet(actionSheet: UIActionSheet, clickedButtonAtIndex buttonIndex: Int) { Flurry.logEvent("Clicked change user avatar") if buttonIndex == 1 { if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)) { let picker = UIImagePickerController() picker.sourceType = UIImagePickerControllerSourceType.Camera picker.mediaTypes = [kUTTypeImage] picker.delegate = self if UIImagePickerController.isCameraDeviceAvailable(UIImagePickerControllerCameraDevice.Front) { picker.cameraDevice = UIImagePickerControllerCameraDevice.Front } else { picker.cameraDevice = UIImagePickerControllerCameraDevice.Rear } delay(0, { () -> () in currentNav().presentViewController(picker, animated: true, completion: nil) }) } } else if buttonIndex == 2 { if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.SavedPhotosAlbum)) { let picker = UIImagePickerController() picker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary picker.mediaTypes = [kUTTypeImage] picker.allowsEditing = false picker.delegate = self delay(0, { () -> () in currentNav().presentViewController(picker, animated: true, completion: nil) }) } } }
下面是有bug的代码:如下,直接获取info字典中UIImagePickerControllerOriginalImage 的image,然后使用框架赋值操作
1 func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) { 2 MBProgressHUD.showHUDAddedTo(self.view, animated: true, needMask: false) 3 let img = info[UIImagePickerControllerOriginalImage] as! UIImage 4 var cropCtrl: RSKImageCropViewController 5 if self.coverChanging { 6 let width = min(UIScreen.mainScreen().bounds.size.width , UIScreen.mainScreen().bounds.size.height) 7 cropCtrl = RSKImageCropViewController(image: img, cropMode: RSKImageCropMode.Custom, cropSize: CGSizeMake(width, width * 10 / 16)) 8 } else { 9 cropCtrl = RSKImageCropViewController(image: img, cropMode: RSKImageCropMode.Circle, cropSize: CGSizeMake(512, 512)) 10 } 11 cropCtrl.delegate = self 12 picker.dismissViewControllerAnimated(false, completion: { [unowned self]() -> Void in 13 self.presentViewController(cropCtrl, animated: false, completion: nil) 14 }) 15 }
代码在iPhone下测试没有问题。在ipad air上测试直接崩溃,我打印出info信息如下:
["UIImagePickerControllerReferenceURL": assets-library://asset/asset.JPG?id=7136137D-8D6C-409D-A4A4-7520924F4AD4&ext=JPG, "UIImagePickerControllerMediaType": public.image]
下面来看看正常的打印info信息的输出:
["UIImagePickerControllerOriginalImage": <UIImage: 0x188a1010> size {480, 640} orientation 3 scale 1.000000, "UIImagePickerControllerMediaMetadata": {
DPIHeight = 72;
DPIWidth = 72;
Orientation = 6;
"{Exif}" = {
ApertureValue = "2.526068811667588";
BrightnessValue = "4.991759637258034";
ColorSpace = 1;
DateTimeDigitized = "2015:10:15 15:32:42";
DateTimeOriginal = "2015:10:15 15:32:42";
ExposureBiasValue = 0;
ExposureMode = 0;
ExposureProgram = 2;
ExposureTime = "0.007518796992481203";
FNumber = "2.4";
Flash = 32;
FocalLenIn35mmFilm = 35;
FocalLength = "1.85";
ISOSpeedRatings = (
125
);
LensMake = Apple;
LensModel = "iPad 2 front camera 1.85mm f/2.4";
LensSpecification = (
"1.85",
"1.85",
"2.4",
"2.4"
);
MeteringMode = 5;
PixelXDimension = 640;
PixelYDimension = 480;
SceneType = 1;
SensingMethod = 2;
ShutterSpeedValue = "7.059855806488952";
SubsecTimeDigitized = 674;
SubsecTimeOriginal = 674;
WhiteBalance = 0;
};
"{MakerApple}" = {
1 = 2;
3 = {
epoch = 0;
flags = 1;
timescale = 1000000000;
value = 9309095690750;
};
4 = 1;
5 = 200;
6 = 224;
7 = 1;
8 = (
"0.006874616",
"-0.2249842",
"-0.9852664"
);
};
"{TIFF}" = {
DateTime = "2015:10:15 15:32:42";
Make = Apple;
Model = "iPad 2";
Software = "8.3";
XResolution = 72;
YResolution = 72;
};
}, "UIImagePickerControllerMediaType": public.image]
从这里可以看出来,直接取值是有很大问题的。
所以我进行了如下操作,判断取值,如果最后imge仍没有值,弹框提示用户重新选择照片。代码如下:
需要导入:
import AssetsLibrary
1 // MARK : - imageCrop 2 func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { 3 MBProgressHUD.showHUDAddedTo(self.view, animated: true, needMask: false) 4 var img = UIImage() 5 if info[UIImagePickerControllerOriginalImage] != nil { 6 img = info[UIImagePickerControllerOriginalImage] as! UIImage 7 self.showRSkImageCropController(picker, img: img) 8 } else if info[UIImagePickerControllerReferenceURL] != nil { 9 let imageUrl = info[UIImagePickerControllerReferenceURL] as! NSURL 10 let assetLibrary = ALAssetsLibrary() 11 assetLibrary.assetForURL(imageUrl, resultBlock: { (asset:ALAsset?) -> Void in 12 if let imageRef = asset?.defaultRepresentation().fullScreenImage() { 13 img = UIImage(CGImage: imageRef as! CGImageRef) 14 self.showRSkImageCropController(picker, img: img) 15 } else { 16 let imageActionSheet = UIActionSheet(title:Localized.PHOTO_CHOSE_ERROR, delegate: nil, cancelButtonTitle:Localized.DIALOG_BUTTON_CANCEL, destructiveButtonTitle:Localized.DIALOG_BUTTON_OK) 17 imageActionSheet.showInView(picker.view) 18 } 19 }) { (error:NSError?) -> Void in 20 let imageActionSheet = UIActionSheet(title:Localized.PHOTO_CHOSE_ERROR, delegate: nil, cancelButtonTitle:Localized.DIALOG_BUTTON_CANCEL, destructiveButtonTitle:Localized.DIALOG_BUTTON_OK) 21 imageActionSheet.showInView(picker.view) 22 } 23 } 24 } 25 26 func showRSkImageCropController(picker:UIImagePickerController,img:UIImage) { 27 var cropCtrl: RSKImageCropViewController 28 if self.coverChanging { 29 let width = min(UIScreen.mainScreen().bounds.size.width , UIScreen.mainScreen().bounds.size.height) 30 cropCtrl = RSKImageCropViewController(image: img, cropMode: RSKImageCropMode.Custom, cropSize: CGSizeMake(width, width * 10 / 16)) 31 } else { 32 cropCtrl = RSKImageCropViewController(image: img, cropMode: RSKImageCropMode.Circle, cropSize: CGSizeMake(512, 512)) 33 } 34 cropCtrl.delegate = self 35 picker.dismissViewControllerAnimated(false, completion: { [unowned self]() -> Void in 36 self.presentViewController(cropCtrl, animated: false, completion: nil) 37 }) 38 }
参考的链接如下:
链接1:http://www.bubuko.com/infodetail-846042.html
链接2:http://www.cnblogs.com/liangxing/archive/2013/01/05/2846136.html
链接3:http://blog.csdn.net/mideveloper/article/details/12997453