iOS - UIImagePicker的简单总结

前言

两年前写ShortenMe的时候,只是简单学习过UIImagePicker的使用。并没有写过什么文档,每次需要使用的时候都是会从网上或者以前的代码中快速学习下。如果有人跑过来问我这个控件怎么使用,我都只回答:稍等!我先看看以前的代码···所以,刚好五一有假期,就想写个关于UIImagePicker的使用心得。尽管网上也是有很多此类文章了。

先来看个问题

同事在写一个使用到UIImagePicker控件的Demo时候遇到了这样的一个问题: viewDidLoad加载UIImagePickViewController没有成功。

 1 - (void)viewDidLoad  2 {  3  [super viewDidLoad];  4     // Do any additional setup after loading the view, typically from a nib. 

 5     if (nil == _imgPicker) {  6         _imgPicker = [[UIImagePickerController alloc] init];  7         _imgPicker.delegate = self;  8  }  9     _imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 10     _imgPicker.allowsEditing = YES; 11  [self presentViewController:_imgPicker animated:NO completion:nil]; 12 }

类似的问题再看看StackOverflow上是怎么说的:

 

大概的意思:
如果viewController是root视图,在它的viewDidLoad方法里不能尝试去加载一个新的视图,因为在这个时候root视图可能还没有完全初始化而无法获取到类似屏幕大小等元素的值。
如果你的root视图是UINavigationController,其他视图也完成了加载,那么在viewDidLoad加载一个新的视图是正常的。
可以通过延时的方法去加载一个新的界面,但是不可靠。不同的设备启动速度会有很大的差别,你无法去预知延时多久合适,而且长了用户体验也不好。
更合适的加载时间是在viewDidAppear。
 
上面所提到的解决方法:
1,在使用performSelector:withObject:afterDelay: 延时执行访问相片库的方法(不可靠,也不推荐)
2,把代码移到viewDidAppear:里面(建议)
3,把viewController转换成UINavigationController的rootViewController,简单的做法:
 1 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  2 {  3     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  4     // Override point for customization after application launch.

 5     self.viewController = [[DPViewController alloc] init];  6     self.navC = [[UINavigationController alloc] initWithRootViewController:self.viewController];  7     

 8     self.window.rootViewController = self.navC;  9  [self.window makeKeyAndVisible]; 10     

11     // Override point for customization after application launch.

12     return YES; 13 }
However,在iOS 7.0以上你还会遇到这样一个问题:Warning: Attempt to present on whose view is not in the window hierarchy!
 
The problem in iOS7 has to do with transitions. It seems that if a previous transition didn't complete and you launch a new one, iOS7 messes the views, where iOS6 seems to manage it correctly.
iOS 7后你加载一个界面没有完成时便加载另外一个界面,可能导致混乱,而出现了上述的问题。
 

正题:照相和相库的访问

sourceType

UI 显示样式sourceType
@property(nonatomic) UIImagePickerControllerSourceType sourceType enum {   UIImagePickerControllerSourceTypePhotoLibrary,   UIImagePickerControllerSourceTypeCamera,   UIImagePickerControllerSourceTypeSavedPhotosAlbum }; typedef NSUInteger UIImagePickerControllerSourceType;

sourceType用来确定用户界面显示的样式(Simulator):

UIImagePickerControllerSourceTypePhotoLibrary VS UIImagePickerControllerSourceTypeSavedPhotosAlbum

UIImagePickerControllerSourceTypePhotoLibrary references the entire photo library, letting the user choose which album. UIImagePickerControllerSourceTypeSavedPhotosAlbum goes straight to the camera roll album without giving the user a choice as to which album to choose from. They're similar, but different. You can get to the camera roll from PhotoLibrary, but you can only access the camera roll from UIImagePickerControllerSourceTypeSavedPhotosAlbum.
大意:UIImagePickerControllerSourceTypePhotoLibrary会引用到所有的相簿,让用户可以选择任意的相簿。而UIImagePickerControllerSourceTypeSavedPhotosAlbum会直接打开相机胶卷。

     
 
UIImagePickerControllerSourceTypeCamera
为了区分是否支持所需引用的sourceType,一般要用到下面这个函数,以便确定sourceType,否则可能会导致Crash。
+ (BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType)sourceType 
 1      if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])  2         {//Camera  3 // [self showCamImagePickView];

 4         if (nil == _imgPicker) {  5             _imgPicker = [[UIImagePickerController alloc] init];  6             _imgPicker.delegate = self;  7  }  8         

 9         _imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera; 10         _imgPicker.allowsEditing = YES; 11  [self presentViewController:_imgPicker animated:NO completion:nil]; 12     }else{ 13         //album 14 // [self showAlbumImagePickerView];

15         UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"ImagePicker" message:@"UIImagePickerControllerSourceTypeCamera Simulator Not Available" delegate:self cancelButtonTitle:@"I Know" otherButtonTitles:nil, nil]; 16  [alert show]; 17     }

 

mediaTypes

@property(nonatomic,copy) NSArray *mediaTypes
 
mediaTypes用来确定再picker里显示那些类型的多媒体文件,图片?视频?
+ (NSArray *)availableMediaTypesForSourceType:(UIImagePickerControllerSourceType)sourceType
 
//  设置所支持的类型,设置只能拍照,或则只能录像,或者两者都可以
NSString *requiredMediaType = ( NSString *)kUTTypeImage;
NSString  *requiredMediaType1 = (  NSString  *) kUTTypeMovie ;
NSArray  *arrMediaTypes=[ NSArray   arrayWithObjects :requiredMediaType, requiredMediaType1, nil ];
[controller  setMediaTypes :arrMediaTypes];
 
 
UIImagePickerControllerDelegate
通过实现 UIImagePickerControllerDelegate 代理的方法来完成用户在选中图片,或者视频时的处理方式:
 
共有三个可选的代理方法
– imagePickerController:didFinishPickingImage:editingInfo:    Deprecated in iPhone OS 3.0
– imagePickerController:didFinishPickingMediaWithInfo:  
– imagePickerControllerDidCancel:  
 
其中最主要的处理方法:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
info中包括选取的照片,视频的主要信息
NSString *const UIImagePickerControllerMediaType;         选取的类型  public.image    public.movie
NSString *const UIImagePickerControllerOriginalImage;    修改前的UIImage object.
NSString *const UIImagePickerControllerEditedImage;      修改后的UIImage object.
NSString *const UIImagePickerControllerCropRect;           原始图片的尺寸NSValue object containing a CGRect data type
NSString *const UIImagePickerControllerMediaURL;          视频在文件系统中 的 NSURL地址

保存视频时通过获取其NSURL 然后转换成NSData。

 
Demo - Library or Album
 1 #pragma mark -

 2 //访问相库

 3 - (void) showAlbumImagePickerView

 4 {

 5     if (nil == _imgPicker) {

 6         _imgPicker = [[UIImagePickerController alloc] init];

 7         _imgPicker.delegate = self;

 8     }

 9     

10     _imgPicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;

11     _imgPicker.allowsEditing = YES;

12     [self.navigationController presentViewController:_imgPicker animated:YES completion:nil];

13 }

14 

15 //访问照相机

16 - (void) showCamImagePickView

17 {

18     if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])

19         {//Camera

20         if (nil == _imgPicker) {

21             _imgPicker = [[UIImagePickerController alloc] init];

22             _imgPicker.delegate = self;

23         }

24         _imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;

25         _imgPicker.allowsEditing = YES;

26         _imgPicker.cameraFlashMode = UIImagePickerControllerCameraFlashModeOff;

27         

28         [self.navigationController presentViewController:_imgPicker animated:YES completion:nil];

29     }else{

30         //album

31         [self showAlbumImagePickerView];

32     }

33 }

 

测试代码如上,封装两个方法来分别打开相库、照相功能。
实现代理 UIImagePickerControllerDelegate的两个 回调方法:
 1 #pragma mark -

 2 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

 3 {

 4         NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];

 5         UIImage *image = nil;

 6     UIImage *editImg = nil;

 7     CGRect rect = CGRectZero;

 8     

 9         if ([mediaType isEqualToString:@"public.image"])

10         {

11                 image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];

12         editImg = [info objectForKey:@"UIImagePickerControllerEditedImage"];

13         rect = [[info objectForKey:@"UIImagePickerControllerCropRect"] CGRectValue];

14         }

15 

16         [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;

17     [picker dismissViewControllerAnimated:NO completion:nil];

18 }

19 

20 - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker

21 {

22     [picker dismissViewControllerAnimated:NO completion:^{

23         switch (picker.sourceType) {

24             case UIImagePickerControllerSourceTypeCamera:

25                 [self showAlbumImagePickerView];

26                 break;

27             case UIImagePickerControllerSourceTypeSavedPhotosAlbum:

28             case UIImagePickerControllerSourceTypePhotoLibrary:

29                 [self showCamImagePickView];

30             default:

31                 break;

32         }

33     }];

34 }
其中在 – imagePickerController:didFinishPickingMediaWithInfo:  方法中,我们会尝试去读取information的值,并且做个预览。
在模拟器中测试,只能尝试访问相片库了。整个效果流程如下:
                  
在点击Choose之后,我们可以在回调代码里面预览图像数据
 
 
假如将imagePicker的allowsEditting属性值改为NO,则不会出现上面的编辑界面,并且editImg、rect值均为nil。
你也可以根据项目需求修改sourceType, UIImagePickerControllerS ourceTypePhotoLibrary和 UIImagePickerControllerS ourceTypeSavedPhotosAlbu m的区别见上文。
 
Demo - Camera
 
需要用真机才能体验到效果。
 
修改Camera的界面:(待写)

你可能感兴趣的:(uiimage)