使用场景:在使用AlertView(已弃用)或UIImagePickerController这类方法时,执行操作后是需要在代理方法中实现回调的,日常应用中很多时候在调用的地方会有我们需要用到的参数,这样我们就需要用属性去记录调用方法中的参数,这样用着很是不爽,这里用两个例子来实现在当前方法中使用block来获取代理方法中的参数,使用的是runtime。
如果runtime的方法索引不出来,那么可以尝试一下两种方法
1.
#import <objc/runtime.h>
#import <objc/message.h>
2.在"Target - Build Settings"搜索msgSend,修改"Enable Strict Checking of objc_msgSend Calls"的值为"No"
AlertView的例子:
// 定义静态常量
static void *EOCMyAlertViewKey = "EOCMyAlertViewKey";
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"标题" message:@"内容" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"Continue", nil];
void (^block)(NSInteger) = ^(NSInteger buttonIndex) {
NSLog(@"%ld", buttonIndex);
};
objc_setAssociatedObject(alert, EOCMyAlertViewKey, block, OBJC_ASSOCIATION_COPY);
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
void (^block)(NSInteger) = objc_getAssociatedObject(alertView, EOCMyAlertViewKey);
block(buttonIndex);
}
没错,上面这段代码是学的书里的,下面这段代码是用上面的方法实现的UIImagePickerController的回调。
// 定义静态常量
static void *PickerKey = "pickerKey";
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UIAlertAction *cameraAction = [UIAlertAction actionWithTitle:@"拍照" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.delegate = self;
void (^block) (NSString *) = ^(NSString *imageUrlString) {
ZHDebugLog(@"%@", imageUrlString);
};
objc_setAssociatedObject(picker, PickerKey, block, OBJC_ASSOCIATION_COPY);
[self presentViewController:picker animated:YES completion:nil];
}];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"系统检测到您已经更换手机或更新手机系统,需要您拍摄本人照片打卡" preferredStyle:UIAlertControllerStyleAlert];
[alertVc addAction:cameraAction];
[alertVc addAction:cancelAction];
[self presentViewController:alertVc animated:YES completion:nil];
}
// UIImagePickerController代理方法
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info {
[picker dismissViewControllerAnimated:YES completion:nil];
UIImage *img = info[@"UIImagePickerControllerOriginalImage"];
// 上传图片,获取到图片路径
[ZHNetworkManager zh_uploadImage:img folder:@"ReplacePhoneClickInImage" success:^(NSString *imageUrlString) {
void (^block) (NSString *) = objc_getAssociatedObject(picker, PickerKey);
block(imageUrlString);
}];
}
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy)
id object:表示关联者,是一个对象。
const void * _Nonnull key:关联者的索引key
id _Nullable value:被关联者,这里是一个block
objc_AssociationPolicy policy:关联时采用的协议,有assign, retain, copy
在block的回调里要注意使用weakSelf防止循环引用。
文章不易过长,否则连我自己都不爱看了!
网友评论