iOS 에서 Runtime 의 몇 가지 기본 용법 기록

7618 단어 iosruntime사용법
런 타임 소개
런 타임 구현 에 대한 세부 사항 을 소개 하 는 글 이 아니 라 오 브 젝 티 브-C 가 제공 하 는 런 타임 API 를 어떻게 활용 해 개발 하 는 지 에 대한 글 입 니 다!
Objective-C 는 프로그램 을 실행 할 때 상당히 많은 동적 특성 을 가지 고 있 습 니 다.
Objctive-C Runtime 은 실행 중인 라 이브 러 리 로 C 와 어 셈 블 리 로 이 루어 집 니 다.Runtime 을 통 해 포 장 된 C 구조 체 와 함 수 는 프로그램 이 실 행 될 때 클래스 와 대상 및 그 방법 을 만 들 고 검사 하 며 수정 할 수 있 으 며 심지어 교체 하거나 교환 할 수 있 습 니 다.
런 타임 에 대한 기본 적 인 사용법 을 적어 보도 록 하 겠 습 니 다.
1)메시지 메커니즘
OOP 용어 에서 메시지 전달 은 대상 간 에 메 시 지 를 보 내 고 받 는 통신 모드 를 말한다.
Objective-C 에서 메 시 지 는 호출 클래스 와 클래스 인 스 턴 스 방법,즉 수신 자가 실행 해 야 할 메 시 지 를 받 는 데 사 용 됩 니 다.
사용 사례

//        
Class catClass = objc_getClass("Cat"); 
 
//  Class       ,          , Class  alloc  
Cat *cat = objc_msgSend(catClass, @selector(alloc)); 
 
//  init   Cat  cat
cat = objc_msgSend(cat, @selector(init)); 
 
//  eat   cat,   eat  
objc_msgSend(cat, @selector(eat));
 
//        
objc_msgSend(objc_msgSend(objc_msgSend(objc_getClass("Cat"), sel_registerName("alloc")), sel_registerName("init")), sel_registerName("eat"));
2)방법 교환 방법 Swizzling
Objective-C 는 동적 교체 방법 이나 인 스 턴 스 방법 에 사용 할 API 를 제공 합 니 다.
  • class_replace Method 교체 방법의 정의
  • method_exchange Implementations 교환 두 가지 방법의 실현(구체 적 인 사용 사례 는 다음 과 같다)
  • method_setImplementation 설정 방법의 실현
  • 주:classreplace Method 가 존재 하지 않 는 방법 을 바 꾸 려 고 할 때 class 를 호출 합 니 다.addMethod 는 이 클래스 에 새로운 방법 을 추가 합 니 다.
    사용 사례
    
    //Cat.m
    
    + (void)load{
     Method eatMethod = class_getInstanceMethod(self, @selector(eat));
      Method shirtMethod = class_getInstanceMethod(self, @selector(shirt));
     
     method_exchangeImplementations(eatMethod, shirtMethod);
    }
    
    - (void)eat{
     NSLog(@"cat eat....");
    }
    
    - (void)shirt{
     NSLog(@"cat shirt....");
    }
    3)동적 로드 방법
    실현 되 지 않 은 방법 을 호출 하거나 알 수 없 는 메 시 지 를 수신 자 에 게 보 낼 때 메시지 의 수신 자 는 resolve InstanceMethod 를 호출 합 니 다.
    사용 사례
    
    // Cat.m
    
    //An Objective-C method is simply a C function that take at least two arguments―self and _cmd. 
    void run(id self, SEL _cmd, NSNumber *number){
     NSLog(@"run for %@", number);
    }
    
    //  run:    ,           
    + (BOOL)resolveInstanceMethod:(SEL)sel{
     if(sel == NSSelectorFromString(@"run:")){
      class_addMethod(self, @selector(run:), run, "v@:@");
      return YES;
     }
     return [super resolveInstanceMethod:sel];
    }
    
    //          resolveClassMethod
    4)메시지 전달
    
    //    ,                ,       ,                
    //   YES    selector        ,           ,    NO
    + (BOOL)resolveInstanceMethod:(SEL)sel {
     return YES;
    }
    
    //    ,         NO       YES       ,      
    //       ,                        ,       self     
    - (id)forwardingTargetForSelector:(SEL)aSelector {
     return nil;
    }
    
    
    //    ,   forwardingTargetForSelector:   nil,        ,             『    (Type Encoding)』
    //     nil,        ,        
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
     return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    
    //         ,-doesNotRecognizeSelector:       
    //          
    - (void)forwardInvocation:(NSInvocation *)anInvocation {
     //             
     [anInvocation setSelector:@selector(unknown)];
     //         ,          
     [anInvocation invokeWithTarget:self];
    }
    
    - (void)unknown {
     NSLog(@"unkown method.......");
    }
    
    //            forwardInvocation       
    - (void)doesNotRecognizeSelector:(SEL)aSelector {
     NSLog(@"unresolved method :%@", NSStringFromSelector(aSelector));
    }
    주:"유형 인 코딩(유형 인 코딩)"
    5)동적 관련 속성
    대상 이 메모리 에 있 는 배열 은 하나의 구조 체 로 볼 수 있 습 니 다.이 구조 체 의 크기 는 동적 으로 변화 할 수 없 기 때문에 실행 할 때 동적 으로 대상 에 게 구성원 변 수 를 증가 시 킬 수 없습니다.상대 적 으로 대상 의 방법 정 의 는 클래스 의 가 변 영역 에 저 장 됩 니 다.
    아래 그림 에서 보 듯 이 Class 의 설명 정보 입 니 다.그 중에서 methodList 는 클래스 에서 정의 할 수 있 는 방법의 지침 입 니 다.이 지침 이 가리 키 는 지침 의 값 을 수정 함으로써 우 리 는 클래스 동적 증가 방법 으로 실현 할 수 있 습 니 다.
    따라서 우 리 는 동태 적 으로 구성원 을 늘 리 는 방법 을 실현 할 수 있 지만 구성원 변 수 를 직접적 으로 증가 시 킬 수 없다.이것 이 바로 category 의 실현 원리 이다.
    
    //<objc/runtime.h>
    
    struct objc_class {
     Class isa OBJC_ISA_AVAILABILITY;
    
    #if !__OBJC2__
     Class super_class          OBJC2_UNAVAILABLE;
     const char *name           OBJC2_UNAVAILABLE;
     long version            OBJC2_UNAVAILABLE;
     long info            OBJC2_UNAVAILABLE;
     long instance_size          OBJC2_UNAVAILABLE;
     struct objc_ivar_list *ivars        OBJC2_UNAVAILABLE;
     struct objc_method_list **methodLists     OBJC2_UNAVAILABLE;
     struct objc_cache *cache         OBJC2_UNAVAILABLE;
     struct objc_protocol_list *protocols      OBJC2_UNAVAILABLE;
    #endif
    
    } OBJC2_UNAVAILABLE;
    사용 사례
    
    //Cat+Extend.h
    
    @interface Cat (extend)
    
    @property(nonatomic, copy) NSString *name;
    
    @end
    
    
    //Cat+Extend.m
    
    @implementation Cat (extend)
    
    - (void)setName:(NSString *)name{
     objc_setAssociatedObject(self, "name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (NSString *)name{
     return objc_getAssociatedObject(self, "name");
    }
    
    @end
    6)사전 회전 모델 응용
    Class 의 구조 체 내용 을 통 해 ivars 포인터 가 클래스 의 구성원 변 수 를 포함 하 는 구조 체 를 가리 키 는 것 을 볼 수 있 습 니 다.이 를 통 해 클래스 에서 정 의 된 구성원 변 수 를 얻 을 수 있 고 Objective-C 에서 해당 하 는 API 방법 을 제공 합 니 다:classcopyIvarList
    
    //<objc/runtime.h>
    
    struct objc_class {
     Class isa OBJC_ISA_AVAILABILITY;
    
    #if !__OBJC2__
     Class super_class          OBJC2_UNAVAILABLE;
     const char *name           OBJC2_UNAVAILABLE;
     long version            OBJC2_UNAVAILABLE;
     long info            OBJC2_UNAVAILABLE;
     long instance_size          OBJC2_UNAVAILABLE;
     struct objc_ivar_list *ivars        OBJC2_UNAVAILABLE;
     struct objc_method_list **methodLists     OBJC2_UNAVAILABLE;
     struct objc_cache *cache         OBJC2_UNAVAILABLE;
     struct objc_protocol_list *protocols      OBJC2_UNAVAILABLE;
    #endif
    
    } OBJC2_UNAVAILABLE;
    사용 사례
    
    //Cat.h
    
    @property(nonatomic, copy) NSString *cid;
    
    @property(nonatomic, copy) NSString *age;
    
    + (instancetype)modelWithDict:(NSDictionary *)dict;
    
    
    //Cat.m
    
    + (instancetype)modelWithDict:(NSDictionary *)dict{
     id model = [[self alloc] init];
     unsigned int count = 0;
     
     Ivar *ivars = class_copyIvarList(self, &count);
     for (int i = 0 ; i < count; i++) {
      Ivar ivar = ivars[i];
      
      NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
      
      //    ,         _cid,_age
      ivarName = [ivarName substringFromIndex:1];
      id value = dict[ivarName];
      
      [model setValue:value forKeyPath:ivarName];
     }
     
     return model;
    }
    총결산
    이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기