在某些情況下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
疑惑點:
- 檢查確實是已經設置了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,一定要耐心從根源上分析問題,不能按照看到的表象來判斷代碼走的邏輯。
另外不光要注意內存泄漏,也要注意指針是否為空啊。