一、功能简介
1、封装了一个按钮,点击按钮,会提示从何处获取图片:如果设备支持相机,可以从相机获取,同时还可以从手机相册获取图片。
2、选择图片后,有一个block回调,根据需求,将获得的图片拿来使用。
3、提供了初始化方法,可以灵活定义按钮,包括把返回的图片设置给按钮自己。
二、核心原理
1、UIAlertController 提示框
2、UIImagePickerController 图片拾取控制器
3、isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera 类方法,判断是否支持相机
4、遵守UIImagePickerControllerDelegate,UINavigationControllerDelegate
5、实现代理方法获得图片:- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
6、UIImageJPEGRepresentation 方法将图片压缩转换层NSData,然后写入沙盒
三、源码
1、.h文件
@interface ZQImageToolsButton : UIButton /** * 可以获得储存图片信息的字典,里面包含了沙盒里的图片完整路径(程序每次运行沙盒的路径可能会不同,但是图片名不变) * * @return */ -(NSDictionary * )getImageInfro; /** * 初始化方法,点击按钮可以选择从相册或是相机(如果有相机)选择图片并返回图片 * * @param title 按钮的名字 * @param frame 按钮的frame * @param controller 按钮所在的控制器,弹出对话框的控制器 * @param block 获得图片后的回调 * @param imageName 储存在沙盒里图片的名字 * * @return 返回一个按钮 */ -(instancetype)initWithTitle:(NSString *)title frame:(CGRect)frame controller:(UIViewController *)controller imageBlock:(void(^)(UIImage *))block imageName :(NSString *)imageName; @end
2、.m文件
@interface ZQImageToolsButton() <UIImagePickerControllerDelegate,UINavigationControllerDelegate> @property(nonatomic,weak) UIViewController * controller; @property(nonatomic,copy) void(^imageBlock)(UIImage *) ; @property(nonatomic,strong) NSString * imageName; @property(nonatomic,strong) NSDictionary * imageInfro; @end @implementation ZQImageToolsButton -(NSDictionary * )getImageInfro { return self.imageInfro; } -(instancetype)initWithTitle:(NSString *)title frame:(CGRect)frame controller:(UIViewController *)controller imageBlock:(void(^)(UIImage *))block imageName :(NSString *)imageName { self = [[ZQImageToolsButton alloc]initWithFrame:frame]; self.imageBlock = block; self.controller = controller; self.imageName = imageName; [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [self setTitle:title forState:UIControlStateNormal]; [self addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside]; return self ; } - (void)btnClick:(UIButton *) btn { // 创建图片管理器、 跳转到相机或相册页面 UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init]; imagePickerController.delegate = self; imagePickerController.allowsEditing = YES; //创建弹框 UIAlertController * av = [UIAlertController alertControllerWithTitle:@"选择" message:@"从您的相册/相机选择" preferredStyle:UIAlertControllerStyleActionSheet]; //设置image管理器的源类型 __block NSInteger sourceType = 0; UIAlertAction * photo = [UIAlertAction actionWithTitle:@"我的相册" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { //图片源为相册 sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; imagePickerController.sourceType = sourceType; [self.controller presentViewController:imagePickerController animated:YES completion:^{}]; }]; UIAlertAction * camera = [UIAlertAction actionWithTitle:@"我的相机" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { //图片源为相机 sourceType = UIImagePickerControllerSourceTypeCamera; imagePickerController.sourceType = sourceType; [self.controller presentViewController:imagePickerController animated:YES completion:^{}]; }]; UIAlertAction * cancle = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { //取消 }]; //判断是否支持相机 if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { [av addAction:photo]; [av addAction:camera]; [av addAction:cancle]; } else { //如果不支持相机,就不用把相机按钮加入提示框了 [av addAction:photo]; [av addAction:cancle]; } [self.controller presentViewController:av animated:YES completion:nil]; } // 图片选择结束之后,走这个方法,字典存放所有图片信息 #pragma mark - image picker delegte 系统代理,返回从相册中选中的图片 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { [picker dismissViewControllerAnimated:YES completion:^{ NSLog(@"选好图片了"); }]; //获得选中的图片了! UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; //block回调,获得图片后,交给控制器 self.imageBlock(image); // 保存图片至本地,用传进来的名字重新拼接图片名字 NSString * imgName = [NSString stringWithFormat:@"SavedImage-%@.png",self.imageName]; //拼接保存至沙盒的路径 NSString *fullPath = [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:imgName]; //记录一下图片的信息,存到字典中,需要的时候可以访问 NSDictionary *dic = @{@"image":fullPath}; self.imageInfro = dic; //保存到沙盒 [self saveImage:image withName:imgName filePath:fullPath]; } //保存至沙盒 - (void) saveImage:(UIImage *)currentImage withName:(NSString *)imageName filePath:(NSString *)filePath { //压缩比例0.5 NSData * imageData = UIImageJPEGRepresentation(currentImage, 0.5); // 将图片写入文件 [imageData writeToFile:filePath atomically:NO]; } @end
四、其他补充
1、imagePickerController didFinishPickingImage 这个代理方法被遗弃了。。
imagePickerController didFinishPickingMediaWithInfo 这个方法被推荐
2、获取图片时的内存暴涨问题
(1)获取的图片全部原封不动的加载到内存中,可能会造成内存的暴涨。
(2)设置属性allowsEditing 为YES,可解决内存暴涨,对于图片进行了处理
(3)如果使用上面的第二个方法返回图片,allowsEditing也解决不了内存暴涨(什么鬼。。)
3、使用imagePickerController时,最好先判断源可用:isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera
五、扩展
1、本例没有实现图片的多选
2、本例没有实现上传图片的业务逻辑
3、小东西,供娱乐交流使用