iOS-runtimeの一般的な方法の例

31393 ワード

  • で使用されるカスタムクラス:
  • #import 
    
    @interface Person : NSObject
    
    @property(nonatomic,copy) NSString *name;
    @property(nonatomic,copy) NSString *sex;
    -(NSString *)sayName;
    -(NSString *)saySex;
    
    @end
  • 動的変数制御
  • - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.person = [Person new];
        _person.name = @"xiaoming";
        NSLog(@"XiaoMing first answer is %@",self.person.name);
        
        [self sayName];
    }
    
    - (void)sayName
    {
        unsigned int count = 0;
        Ivar *ivar = class_copyIvarList([self.person class], &count);
        for (int i = 0; i) {
            Ivar var = ivar[i];
            const char *varName = ivar_getName(var);
            NSString *proname = [NSString stringWithUTF8String:varName];
            
            if ([proname isEqualToString:@"_name"]) {   //            
                object_setIvar(self.person, var, @"daming");
                break;
            }
        }
        NSLog(@"XiaoMing change name  is %@",self.person.name);
    }
  • 動的追加方法
  • - (void)viewDidLoad {
        [super viewDidLoad];
        self.person = [Person new];
        [self sayFrom];
    }
    
    - (void)sayFrom
    {
        class_addMethod([self.person class], @selector(guess), (IMP)guessAnswer, "v@:");
        if ([self.person respondsToSelector:@selector(guess)]) {
            //Method method = class_getInstanceMethod([self.xiaoMing class], @selector(guess));
            [self.person performSelector:@selector(guess)];
            
        } else{
            NSLog(@"Sorry,I don't know");
        }
    }
    
    void guessAnswer(id self,SEL _cmd){
        NSLog(@"function: guessAnswer");
        NSLog(@"__%@__", NSStringFromSelector(_cmd));
    }
    
    - (void) guess{
        NSLog(@"function: guess");
        NSLog(@"__%@__", NSStringFromSelector(_cmd));
    }
  • 動的交換の2つの方法の実装
  • - (void)viewDidLoad {
        [super viewDidLoad];
        self.person = [Person new];
        
        NSLog(@"%@",_person.sayName);
        NSLog(@"%@",_person.saySex);
        
        Method m1 = class_getInstanceMethod([self.person class], @selector(sayName));
        Method m2 = class_getInstanceMethod([self.person class], @selector(saySex));
      
        method_exchangeImplementations(m1, m2);
    }
  • ブロック置換方法
  • @interface Tool : NSObject
    
    + (instancetype)sharedManager;
    - (NSString *)changeMethod;
    - (void)addCount;
    
    @end
    
    #import "Tool.h"
    
    @interface Tool ()
    
    @property (nonatomic, assign) NSInteger count;
    
    @end
    
    @implementation Tool
    
    + (instancetype)sharedManager {
        static Tool *_sInstance;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _sInstance = [[Tool alloc] init];
        });
        
        return _sInstance;
    }
    
    - (NSString *)changeMethod
    {
        return @"haha,          ";
    }
    
    - (void)addCount
    {
        _count += 1;
        
        NSLog(@"    ------%ld", _count);
    }
    
    @end
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        //        [self.person class],       
        Method m1 = class_getInstanceMethod([Person class], @selector(sayName));
        Method m2 = class_getInstanceMethod([Tool class], @selector(changeMethod));
        
        method_exchangeImplementations(m1, m2);
    }
  • メソッドに追加機能
  • を追加
    @implementation FiveViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.view.backgroundColor = [UIColor whiteColor];
        UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        button.frame = CGRectMake(100, 100, 100, 100);
        [button setTitle:@"  " forState:UIControlStateNormal];
        [button addTarget:self action:@selector(ButtonClick) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:button];
    }
    
    - (void)ButtonClick
    {
        NSLog(@"      ");
    }
    
    @end
  • runtimeをまとめ、コードは以下の通り:
  • 1、ランタイムヘッダファイルをロードする:
    #import 

    2、具体的な実装コード:
    
    /**     :MyObject */
    //   
    #import 
    
    @interface MyObject : NSObject
    @property(strong,nonatomic) NSString *string;
    @property(strong,nonatomic) NSArray  *array;
    
    - (void)method1;
    - (void)method2;
    - (void)classMethod1;
    @end
    
    //   
    #import "MyObject.h"
    #import 
    @interface MyObject (){
        NSInteger _instance1;
        NSString  *_instance2;
    }
    
    @property(assign,nonatomic) NSInteger intrger;
    - (void)method3WithArge1:(NSInteger)arge1 arge2:(NSString *)arge2;
    @end
    @implementation MyObject -(void)classMethod1{ } - (void)method1{ NSLog(@"cell Method1"); } - (void)method2{ } - (void)method3WithArge1:(NSInteger)arge1 arge2:(NSString *)arge2{ NSLog(@"arge1 %ld arge2 %@",arge1,arge2); } + (BOOL)resolveInstanceMethod:(SEL)sel{ NSString *selector = NSStringFromSelector(sel); if ([selector isEqualToString:@"method1"]) { class_addMethod(self.class, @selector(method1), (IMP)functionForMethod1, "@:"); } return [super resolveInstanceMethod:sel]; } void functionForMethod1(id self,SEL _cmd){ NSLog(@"%@ %p",self,_cmd); } - (instancetype)forwardingTargetForSelector:(SEL)aSelector{ NSString *selector = NSStringFromSelector(aSelector); if([selector isEqualToString:@"method2"]){   //return; } return [super forwardingTargetForSelector:aSelector]; } - (void)forwardInvocation:(NSInvocation *)anInvocation{ } @end /** */ #import @implementation ViewController - (void)viewDidLoad { [super viewDidLoad];   //1.   // ViewController NSLog(@"%s",class_getName([self class]));   //   //This is superClass 0x10f426da0 isa NSLog(@"This is superClass %p",class_getSuperclass([self class]));   //   //Is MateClass 0 NSLog(@"Is MateClass %d",class_isMetaClass([self class]));   //   //848 size_t a = class_getInstanceSize([self class]); NSLog(@"%ld",a); unsigned int outCount = 0; MyObject *objtect = [[MyObject alloc] init]; Class cls = objtect.class; // NSLog(@"Class name %s",class_getName(cls)); // NSLog(@"SuperClass name %s",class_getName(class_getSuperclass(cls))); // NSLog(@"Is MetaClass %@",(class_isMetaClass(cls))?@"":@"NOT"); // NSLog(@"MyObject size %ld",class_getInstanceSize(cls)); // Ivar string = class_getInstanceVariable(cls, "_string"); if (string != NULL) { NSLog(@"MyObject instance messge %s",ivar_getName(string)); } // objc_property_t *v = class_copyPropertyList(cls, &outCount); for (NSInteger i = 0; i< outCount; i++) { objc_property_t property = v[i]; NSLog(@"property is %s ",property_getName(property)); } free(v); // Ivar *vars = class_copyIvarList(cls, &outCount); for (NSInteger i =0; i< outCount; i++) { Ivar ivar = vars[i]; NSLog(@"copyIvarList is %s is %ld",ivar_getName(ivar),i); } free(vars); // Method *methods = class_copyMethodList(cls, &outCount); for (NSInteger i =0; i< outCount; i++) { Method met = methods[i]; #pragma clang diagnostic ignored"-Wformat" NSLog(@"Method is %s",method_getName(met)); } free(methods); // Format specifies type 'char *' but the argument has type 'SEL _Nonnull' // Method method = class_getInstanceMethod(cls,@selector(method1)); NSLog(@"Method name is %s",method_getName(method)); // #pragma clang diagnostic ignored"-Wundeclared-selector" NSLog(@"Have you method %d",class_respondsToSelector(cls, @selector(method3WithArge1:arge2:))); // IMP imp = class_getMethodImplementation(cls, @selector(method1)); imp(); // #pragma clang diagnostic ignored" -Wunused-variable" // : , objc_allocateClassPair objc_registerClassPair // 1. MySubClass // class, , Class myClass = objc_allocateClassPair(objtect.class, "MySubClass", 0); // 2. , // : v@: v void @: if( class_addMethod(myClass, @selector(mysubMethod1),(IMP)mysubMethod1, "v@:")){ class_replaceMethod(myClass, @selector(method1), (IMP)mysubMethod1,"v@:"); } /* 3. NSSsting myString size sizeof(NSString) log2(sizeof(NSString*)) @encode(NSString*) class_addIvar(class, , size, , ) */ // BOOL isd = class_addIvar(myClass, "_myString", sizeof(NSString *), log(sizeof(NSString *)), @encode(NSString *)); NSLog(@" %d",isd); /* T@encode(type) , V , , property_getAttributes R readonly C copy & retain ARC strong N nonatomic G(name) getter=(name) S(name) setter=(name) D @dynamic W weak P */ //@T objc_property_attribute_t type; type.name = "T"; type.value = @encode(NSString *); //copy objc_property_attribute_t owership = {"C",""}; //nonatomic objc_property_attribute_t oeership2 = {"N",""}; //V_ objc_property_attribute_t var = {"V","_myString"}; // objc_property_attribute_t attributes[] = {type,owership,oeership2,var}; // myString , attributes class_addProperty(myClass, "myString", attributes, 4); unsigned int propertyCount; objc_property_t * properties = class_copyPropertyList(myClass, &propertyCount); for (int i = 0; i) { NSLog(@" : %s",property_getName(properties[i])); NSLog(@" : %s",property_getAttributes(properties[i])); } // free(properties); // objc_allocateClassPair objc_registerClassPair(myClass); id instance = [[myClass alloc] init]; [instance performSelector:@selector(mysubMethod1)]; [instance performSelector:@selector(method1)]; // // , , //objc_disposeClassPair(myClass); // UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)]; view.backgroundColor = [UIColor redColor]; [view setTapActionWithBlock:^{ NSLog(@"saAS"); }]; [self.view addSubview:view];   //SEL   //Objective-C , 、 , (Int ), SEL   //SEL ( , hash KEY ,   // ,   //sel : 0x104dd7735 /* SEL: sel_registerName Objective-C @selector() NSSelectorFromString() */ SEL sel1 = @selector(method1); NSLog(@"sel : %p", sel1); } static void mysubMethod1(id self,SEL _cmd){ NSLog(@" "); } @end

     
    転載先:https://www.cnblogs.com/xujinzhong/p/8549132.html