美文网首页
iOS开发 使用block在当前方法中获取代理方法中的参数

iOS开发 使用block在当前方法中获取代理方法中的参数

作者: 菊上一枝梅 | 来源:发表于2018-12-24 21:25 被阅读7次

使用场景:在使用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防止循环引用。

文章不易过长,否则连我自己都不爱看了!

相关文章

网友评论

      本文标题:iOS开发 使用block在当前方法中获取代理方法中的参数

      本文链接:https://www.haomeiwen.com/subject/vmstlqtx.html