runtime之@dynamic属性

来源:互联网 发布:各种网络协议的区别 编辑:程序博客网 时间:2024/05/17 01:29

@dynamic属性用于通知编辑器不要生成属性对应的实例变量和setter getter 方法,但是在编译时期调用对应的存取方法不会报错,再次验证了OC是一门动态语言

#import <Foundation/Foundation.h>@interface AutoDictionary : NSObject@property (nonatomic, copy) NSString *string;@property (nonatomic, strong) NSNumber  *number;@property (nonatomic, strong) NSDate  *date;@end
#import "AutoDictionary.h"@interface AutoDictionary ()@property (nonatomic, strong) NSMutableDictionary  *dic;@end@implementation AutoDictionary@dynamic string,date,number;@end

VC里面调用如下:

#import "AutoDictionary.h"@interface ViewController ()@property (nonatomic, strong) AutoDictionary  *autoDict;@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    self.autoDict = [[AutoDictionary alloc] init];    [self.autoDict setNumber:[NSNumber numberWithInt:30]];    self.autoDict.string = [NSString stringWithFormat:@"i an"];    NSLog(@"number %@,string %@",self.autoDict.number,self.autoDict.string);}

崩溃信息如下:

 Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[AutoDictionary setNumber:]: unrecognized selector sent to instance 0x60800001c200

利用运行时动态添加存取方法

#import "AutoDictionary.h"#import <objc/runtime.h>@interface AutoDictionary ()@property (nonatomic, strong) NSMutableDictionary  *backStore;@end@implementation AutoDictionary@dynamic string,date,number;-(instancetype)init{    self = [super init];    if (self) {        _backStore = [NSMutableDictionary new];    }    return self;}+(BOOL)resolveInstanceMethod:(SEL)sel{    NSString *selName = NSStringFromSelector(sel);    if ([selName hasPrefix:@"set"]) {        class_addMethod(self, sel, (IMP)autoDictSetter, "V@:@");        return YES;    }else{        class_addMethod(self, sel, (IMP)autoDictGetter, "@@:");        return YES;    }}void autoDictSetter(id self,SEL _cmd,id value){    AutoDictionary *typeSelf = (AutoDictionary *)self;    NSMutableDictionary *backStore = typeSelf.backStore;    // the selector will be for example ,'setNumber:'    // we need to remove ':' & 'set'    // SEL类型转为字符串类型    NSString *selectorString = NSStringFromSelector(_cmd);    // 可变字符串才可以进行一系列的替换 删除 操作    NSMutableString *key = [selectorString mutableCopy];    // remove the ':' at the end    [key deleteCharactersInRange:NSMakeRange(key.length - 1, 1)];    // remove the 'set' prefix    [key deleteCharactersInRange:NSMakeRange(0, 3)];   //lower first character    NSString *lowercaseFirstChar = [[key substringToIndex:1] lowercaseString];    [key replaceCharactersInRange:NSMakeRange(0, 1) withString:lowercaseFirstChar];    if (value) {        [backStore setObject:value forKey:key];    }else{        [backStore removeObjectForKey:key];    }}id autoDictGetter(id self,SEL _cmd){    AutoDictionary *typedSelf = (AutoDictionary *)self;    NSMutableDictionary *backStore = typedSelf.backStore;    NSString *key = NSStringFromSelector(_cmd);    return [backStore objectForKey:key];}@end
0 0
原创粉丝点击