iOS UIImagePickerController Bug

Posted wwwwwwwwwwwwdi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS UIImagePickerController Bug相关的知识,希望对你有一定的参考价值。

这是在测试项目的时候,发现上传用户头像有一个问题,然后引发的探索:
代码:

/**
 修改头像
 */
- (void)modifyHeadshot 
    /*头像*/
    NSString *mediaType = AVMediaTypeVideo;
    AVAuthorizationStatus authorizationStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
    if (authorizationStatus == AVAuthorizationStatusRestricted || authorizationStatus == AVAuthorizationStatusDenied) 
        /*询问是否允许使用照相机*/
        UIAlertController * alertC = [UIAlertController alertControllerWithTitle:@"摄像头访问受限" message:@"请去设置中修改权限" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) 
            [self dismissViewControllerAnimated:YES completion:nil];
        ];
        [alertC addAction:action];
        [self presentViewController:alertC animated:YES completion:nil];
    else
        UIAlertController *alertController = [[UIAlertController alloc] init];
        UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"从手机相册选择" style:0 handler:^(UIAlertAction * _Nonnull action) 
            LOG(@"从手机相册选择");

            // 创建图片选择控制器对象
            self.imagePickerController = [[UIImagePickerController alloc] init];
            self.imagePickerController.navigationBar.tintColor = [UIColor blackColor];
            // 设置允许编辑(照片)
            self.imagePickerController.allowsEditing = YES;
            // 设置相册的呈现样式
//            self.imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
            // 设置代理
            self.imagePickerController.delegate = self;
            // 呈现
            [self presentViewController:self.imagePickerController animated:YES completion:nil];
        ];

        UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"拍照" style:0 handler:^(UIAlertAction * _Nonnull action) 
            LOG(@"拍照");
            // 创建图片选择控制器对象
            self.imagePickerController = [UIImagePickerController new];
            self.imagePickerController.navigationBar.tintColor = [UIColor blackColor];
            // 设置允许编辑
            self.imagePickerController.allowsEditing = YES;
            // 设置相册的呈现样式 ---> 从��中
            self.imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
            // 设置代理
            self.imagePickerController.delegate = self;
            // 呈现
            [self presentViewController:self.imagePickerController animated:YES completion:nil];
        ];

        UIAlertAction *action3 = [UIAlertAction actionWithTitle:@"取消" style:1 handler:^(UIAlertAction * _Nonnull action) 
            LOG(@"取消");
        ];
        [alertController addAction:action2];
        [alertController addAction:action1];
        [alertController addAction:action3];
        [self presentViewController:alertController animated:YES completion:nil];
    



/**
 图片返回代理方法
 */
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
    // 将图片变成data,data进行base64编码成字符串
    UIImage *resultImage = info[UIImagePickerControllerEditedImage];
    id cropRect = [info valueForKey:@"UIImagePickerControllerCropRect"];

    NSData *imageData = UIImageJPEGRepresentation(resultImage, 0.1);

    NSString *base64Str = [imageData base64EncodedStringWithOptions:0];

    //调接口传给后台

先来看看Bug长什么样:

上传的是一张纯黄色的图片,然后info[UIImagePickerControllerEditedImage]取得的图片是这样色儿的
可以看到,获得的图片右侧,有一条黑色的长条,查询了一下,发现这里是苹果SDK的一个Bug,
因为SDK中剪切的长方形范围计算错误了,所以,得出的值肯定也就不对了
而且,这个问题,好像并没有引起苹果的注意。。。

所以,既然苹果SDK内的剪切范围计算有问题,那我们就自己来吧!

这里是解决方案


- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
    // 将图片变成data,data进行base64编码成字符串
    //获取原始图片自己处理
    UIImage *resultImage = [info objectForKey:UIImagePickerControllerOriginalImage];
    CGRect crop = [[info valueForKey:@"UIImagePickerControllerCropRect"] CGRectValue];
    resultImage = [self ordinaryCrop:resultImage toRect:crop];

    NSData *imageData = UIImageJPEGRepresentation(resultImage, 0.1);

    NSString *base64Str = [imageData base64EncodedStringWithOptions:0];

    //上传图片到后台


/**
 *  在指定范围内切割图片
 */
- (UIImage *)ordinaryCrop:(UIImage *)imageToCrop toRect:(CGRect)cropRect

    CGImageRef imageRef = CGImageCreateWithImageInRect([imageToCrop CGImage], cropRect);
    UIImage *cropped = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    return cropped;

这样一来,就没有了以前的问题了

参考资料

以上是关于iOS UIImagePickerController Bug的主要内容,如果未能解决你的问题,请参考以下文章

imagePickerController 选择照片时出错

iPhone - 以编程方式删除状态栏

如何调整自定义 UIButton 的图像大小?

从保存的相机胶卷参考 url 设置 uiimageview

Segue 图像到另一个视图控制器的问题

{python之IO多路复用} IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO