在某些情况下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,但是并没有走代理方法。
疑惑点:
- 检查确实是已经设置了picker的delegate。
- 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,一定要耐心从根源上分析问题,不能按照看到的表象来判断代码走的逻辑。
另外不光要注意内存泄漏,也要注意指针是否为空啊。