iOS runtime 탐구 (3): runtime 부터 OC 의 속성 property 이해 하기

7563 단어
네가 알 아야 할 런 타임 이 여기 있어.
전재 출처 를 밝 혀 주 십시오http://www.jianshu.com/p/0623addb6b74
본 고 는 주로 관련 지식 runtime 을 설명 하고 원리 부터 실천 까지 내용 이 너무 많 기 때문에 다음 과 같은 다섯 편의 문장 으로 나 누 어 상세 하 게 설명 하기 때문에 알 아야 할 방향 을 스스로 선택 할 수 있다.
  • runtime 부터 대상 을 대상 으로 하 는 클래스 부터 과정 을 대상 으로 하 는 구조 체 이해
  • runtime 부터: OC 메시지 전송 메커니즘 깊이 이해
  • runtime 부터: OC 의 속성 property 이해
  • runtime 부터: 실천 Category 속성 추가 및 흑 마법 method swizzling
  • runtime 부터: weak 실현 메커니즘 깊이
  • 본 고 는 시리즈 글 의 세 번 째 글 입 니 다. runtime 부터 OC 의 속성 property 를 이해 하고 주로 runtime 에서 속성 property 과 관련 된 바 텀 실현 과 관련 방법 을 설명 합 니 다. 예전 의 블 로 그 는 property 의 바 텀 실현 에 대해 상세 하 게 설명 하 였 기 때문에 본 고 는 더 이상 언급 하지 않 습 니 다. 필요 하 다 면 관련 글 을 볼 수 있 습 니 다. iOS @ property 탐구 (1): 이 글 은 주로 설명 property 의 기초 와 수정자 에 대한 상세 한 설명 을 바탕 으로 iOS @ property 탐구 (2): 이 글 은 주로 코드 이해 property 의 기본 적 인 실현 을 깊이 이해 하고 본 고의 내용 과 매우 중복 되 기 때문에 본 고 는 상기 와 관련 된 내용 을 더 이상 서술 하지 않 는 다.
    본 고 는 runtime 조작 속성 에 관 한 방법 을 설명 할 것 이다.
    먼저 관련 코드 와 property 밑바닥 실현 과 관련 된 두 구조 체 를 되 돌아 본다.
    //OC       
    @interface Person : NSObject
    
    @property (nonatomic, copy) NSString* cjmName;
    @property (nonatomic, assign) NSUInteger cjmAge;
    
    @end
    
    @implementation Person
    
    @synthesize cjmName = _cjmName;
    @synthesize cjmAge = _cjmAge;
    
    @end
    
    
    //clang   .cpp     
    struct _prop_t {
            const char *name;
            const char *attributes;
    };
    
    static struct /*_prop_list_t*/ {
            unsigned int entsize;  // sizeof(struct _prop_t)
            unsigned int count_of_properties;
            struct _prop_t prop_list[2];
    } _OBJC_$_PROP_LIST_Person __attribute__ ((used, section ("__DATA,__objc_const"))) = {
            sizeof(_prop_t),
            2,
            {{"cjmName","T@\"NSString\",C,N,V_cjmName"},
            {"cjmAge","TQ,N,V_cjmAge"}}
    };
    

    상기 코드 를 통 해 알 수 있 듯 이 하나의 @property 속성 은 밑 에 있 는 구조 체 에 대한 설명 이다. 그러면 우 리 는 어떻게 이 구조 체 를 얻 을 수 있 습 니까?다음 코드 를 통 해 가 져 올 수 있 습 니 다:
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            Person* p = [[Person alloc] init];
            p.cjmName = @"Jiaming Chen";
            
            unsigned int propertyCount = 0;
            objc_property_t *propertyList = class_copyPropertyList([p class], &propertyCount);
            for (int i = 0; i < propertyCount; i++) {
                const char* name = property_getName(propertyList[i]);
                const char* attributes = property_getAttributes(propertyList[i]);
                NSLog(@"%s %s", name, attributes);
            }
        }
        return 0;
    }
    

    먼저 objc_property_t 가 무엇 인지 보고 objc/runtime.h 에서 관련 정 의 를 찾 을 수 있 습 니 다.
    typedef struct objc_property *objc_property_t;
    

    이것 은 구조 체 struct objc_property 를 가리 키 는 지침 이다. 이곳 의 구조 체 struct objc_property 는 바로 앞에서 .cpp 파일 중의 struct _prop_t 구조 체 로 class_copyPropertyList 방법 을 통 해 관련 유형의 모든 속성 을 얻 을 수 있다. 구체 적 인 함수 성명 은 다음 과 같다.
    /** 
     * Describes the properties declared by a class.
     * 
     * @param cls The class you want to inspect.
     * @param outCount On return, contains the length of the returned array. 
     *  If \e outCount is \c NULL, the length is not returned.        
     * 
     * @return An array of pointers of type \c objc_property_t describing the properties 
     *  declared by the class. Any properties declared by superclasses are not included. 
     *  The array contains \c *outCount pointers followed by a \c NULL terminator. You must free the array with \c free().
     * 
     *  If \e cls declares no properties, or \e cls is \c Nil, returns \c NULL and \c *outCount is \c 0.
     */
    OBJC_EXPORT objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
        OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
    

    주석 을 통 해 알 수 있 듯 이 첫 번 째 매개 변 수 는 관련 유형의 대상 (의문 이 있 으 면 본 시리즈 의 앞의 두 편의 글 을 조회 할 수 있 습 니 다) 이 고 두 번 째 매개 변 수 는 가리 키 는 지침 unsigned int 으로 property 의 수량 을 가리 키 는 데 사 용 됩 니 다. 이 방법 을 통 해 모든 속성 을 얻 을 수 있 습 니 다. 그 다음 에 property_getNameproperty_getAttributes 방법 으로 이 속성 에 대한 설명 을 얻 을 수 있 습 니 다.nameattributes 값 의 출력 결 과 는 다음 과 같다.
    2017-03-27 09:59:20.914487 OCTest[2467:460742] cjmName T@"NSString",C,N,V_cjmName
    2017-03-27 09:59:20.915321 OCTest[2467:460742] cjmAge TQ,N,V_cjmAge
    
    name 잘 이해 합 니 다. 뒤의 attributes 비 교 를 통 해 그 규칙 을 발견 하기 어렵 지 않 습 니 다. 관심 이 있 는 독자 들 도 몇 가지 유형, 서로 다른 장식 부 property 를 더 설치 하여 수출 을 볼 수 있 습 니 다.
    그 밖 에 하 는 속성 명 에 따라 속성 설명 구조 체 를 얻 고 속성 추가, 속성 교체 등 몇 가지 방법 이 있 습 니 다.
    /** 
     * Returns a property with a given name of a given class.
     * 
     * @param cls The class you want to inspect.
     * @param name The name of the property you want to inspect.
     * 
     * @return A pointer of type \c objc_property_t describing the property, or
     *  \c NULL if the class does not declare a property with that name, 
     *  or \c NULL if \e cls is \c Nil.
     */
    OBJC_EXPORT objc_property_t class_getProperty(Class cls, const char *name)
        OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
        
    /** 
     * Adds a property to a class.
     * 
     * @param cls The class to modify.
     * @param name The name of the property.
     * @param attributes An array of property attributes.
     * @param attributeCount The number of attributes in \e attributes.
     * 
     * @return \c YES if the property was added successfully, otherwise \c NO
     *  (for example, the class already has that property).
     */
    OBJC_EXPORT BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
        OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0);
    
    /** 
     * Replace a property of a class. 
     * 
     * @param cls The class to modify.
     * @param name The name of the property.
     * @param attributes An array of property attributes.
     * @param attributeCount The number of attributes in \e attributes. 
     */
    OBJC_EXPORT void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
        OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0);
    

    간단 한 밤 을 들 어 라.
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            Person* p = [[Person alloc] init];
            p.cjmAge = 20;
            p.cjmName = @"Jiaming Chen";
            
            unsigned int propertyCount = 0;
            objc_property_t *propertyList = class_copyPropertyList([p class], &propertyCount);
            for (int i = 0; i < propertyCount; i++) {
                const char* name = property_getName(propertyList[i]);
                const char* attributes = property_getAttributes(propertyList[i]);
                NSLog(@"%s %s", name, attributes);
            }
            objc_property_attribute_t attributes = {
                "T@\"NSString\",C,N,V_studentIdentifier",
                "",
            };
            class_addProperty([p class], "studentIdentifier", &attributes, 1);
            objc_property_t property = class_getProperty([p class], "studentIdentifier");
            NSLog(@"%s %s", property_getName(property), property_getAttributes(property));
        }
        return 0;
    }
    

    상기 방법 을 통 해 하나의 속성 을 추가 할 수 있 습 니 다. 본인 의 수준 이 유한 하고 실제 개발 에서 상기 방법 을 사용 한 적 이 없 기 때문에 구체 적 인 실제 사례 도 들 수 없 기 때문에 더 이상 군말 하지 않 습 니 다.
    비고
    작가 의 수준 이 제한 되 어 있 기 때문에 오류 가 발생 할 수 있 으 니 문제 가 있 으 면 아낌없이 가르쳐 주 십시오.

    좋은 웹페이지 즐겨찾기