错误日志博客ios学习资料iOS 开发

iOS疑惑--UIImagePickerController不回

2016-07-04  本文已影响1079人  西蒙SIMON

在某些情况下UIImagePickerConroller没有回调到代理方法,最近偶尔遇到了这个问题,网上也有一些人问到,但是没有确切给出答案和分析,这里我说说我遇到的情况。
先说结论,没有回调代理方法,那就是delegate出了问题。

遇到的情况:
没有直接使用UIImagePickerController,而是封装了一层
封装:
HVWOpenAlbumTool.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface HVWOpenAlbumTool : NSObject


- (void)openAlbumWithVC:(UIViewController *)vc completion:(void (^)(UIImage *))completion;

@end

HVWOpenAlbumTool.m

#import "HVWOpenAlbumTool.h"

@interface HVWOpenAlbumTool() <UINavigationControllerDelegate, UIImagePickerControllerDelegate>

@property(nonatomic, copy) void (^didPickImageBlock)(UIImage *);

@end

@implementation HVWOpenAlbumTool

- (void)openAlbumWithVC:(UIViewController *)vc completion:(void (^)(UIImage *))completion {
    _didPickImageBlock = completion;
    
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.delegate = self;
    picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
    [vc presentViewController:picker animated:YES completion:nil];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [picker dismissViewControllerAnimated:YES completion:nil];
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {- 
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
    if (_didPickImageBlock) {
        _didPickImageBlock(image);
    }
    
    [picker dismissViewControllerAnimated:YES completion:nil];
}

@end

调用:
ViewController.m

#import "ViewController.h"
#import "HVWOpenAlbumTool.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *imageView;
- (IBAction)openAlbum:(id)sender;

@end

@implementation ViewController

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

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)openAlbum:(id)sender {
    HVWOpenAlbumTool *tool = [[HVWOpenAlbumTool alloc] init];
    [tool openAlbumWithVC:self completion:^(UIImage *image) {
        _imageView.image = image;
    }];
}
@end

结果:无论是选择照片还是点击取消,都会缩回picker,但是并没有走代理方法。

Paste_Image.png

疑惑点:

  1. 检查确实是已经设置了picker的delegate。
  2. picker点击选择照片、点击取消确实dimiss掉了。

那为什么就是不走代理方法呢?
其实我是犯了一个低级错误,还有UIImagePickController的事件处理误导了我。

我们再看回调用封装类的地方:

- (IBAction)openAlbum:(id)sender {
    HVWOpenAlbumTool *tool = [[HVWOpenAlbumTool alloc] init];
    [tool openAlbumWithVC:self completion:^(UIImage *image) {
        _imageView.image = image;
    }];
} // 到这里,其实tool已经被释放掉了

因为执行完这个方法,tool就被系统释放了,所以picker的delegate自然就是nil了。

那为什么UIImagePickerController选择了照片或点击取消之后能正常运行呢?

我猜测是如果delegate为nil或者没有实现相应的代理方法,UIImagePickerController就会自己dismiss掉。

经过试验,确实如此

改造一下调用:
ViewController.m

#import "ViewController.h"
#import "HVWOpenAlbumTool.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *imageView;
- (IBAction)openAlbum:(id)sender;
@property(nonatomic, strong) HVWOpenAlbumTool *tool;

@end

@implementation ViewController

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

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)openAlbum:(id)sender {
    HVWOpenAlbumTool *tool = [[HVWOpenAlbumTool alloc] init];
    [tool openAlbumWithVC:self completion:^(UIImage *image) {
        _imageView.image = image;
    }];
    _tool = tool;
}
@end

Done!

所以说,开发的时候遇到bug,一定要耐心从根源上分析问题,不能按照看到的表象来判断代码走的逻辑。
另外不光要注意内存泄漏,也要注意指针是否为空啊。

上一篇下一篇

猜你喜欢

热点阅读