UIImagePickerController 的代理方法 didFinishPickingMediaWithInfo: 不直接傳遞觸發按鈕 (sender),需通過成員變量保存引用或Tag 查找間接獲取。
@interface ViewController ()
@property (nonatomic, weak) UIButton *lastTappedButton; // 弱引用避免循環保留
@end
@implementation ViewController
- (IBAction)selectImageTapped:(UIButton *)sender {
self.lastTappedButton = sender; // 保存引用
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info {
// 這裡可以直接使用 self.lastTappedButton
UIButton *triggerButton = self.lastTappedButton;
// 例如:設置按鈕圖片為選中的照片
UIImage *selectedImage = info[UIImagePickerControllerInfoKeyOriginalImage];
[triggerButton setImage:selectedImage forState:UIControlStateNormal];
[picker dismissViewControllerAnimated:YES completion:nil];
self.lastTappedButton = nil; // 用完釋放
}
@end
// 設置按鈕 Tag
button.tag = 1001;
// 代理中查找
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIButton *btn = (UIButton *)[self.view viewWithTag:1001];
// 風險:Tag 可能衝突、view 層級變化導致找不到
}
@interface CustomImagePicker : UIImagePickerController
@property (nonatomic, weak) UIView *sourceView; // 或 UIButton *sourceButton
@end
// 使用時
CustomImagePicker *picker = [[CustomImagePicker alloc] init];
picker.sourceView = sender;
// 代理中強轉獲取
CustomImagePicker *customPicker = (CustomImagePicker *)picker;
UIButton *btn = (UIButton *)customPicker.sourceView;
enum 標記來源類型,配合 sender 統一處理。PHPickerViewController (PhotosUI) 替代 UIImagePickerController,支援多選、隱私權限更友好。核心原則:代理方法不傳 sender 時,由調用方在發起前保存上下文,這是 Cocoa Touch 設計模式的常見慣例。