iOS runtime 실전 응용:연결 대상

3774 단어

전언


시작하기 전에 iOSruntime의 기초 이해편: iOS 내공편:runtime
유통자는 면접을 볼 때'NSArray에 어떻게 속성을 추가하는가(상속을 사용할 수 없다)'라는 질문에 즉시 협박을 당했다. 상속을 사용할 수 없는데 분류를 쓰겠는가?그러나 분류는 방법만 추가할 수 있을 것 같고 속성을 추가할 수 없을 것 같아서 통자는 백 번 생각해도 이해할 수 없었다. 나중에 런타임을 접하고 나서야 문득 깨달았다.

연결 개체란?


관련 대상은 어떤 OC 대상이 하나의 유일한 키를 통해 하나의 클래스에 연결된 실례를 가리킨다.예를 들어 xiaoming은 Persong류의 실례이다. 그의 Dog(OC 대상)은 밧줄(key)을 통해 그에게 끌려 산책을 한다. 이것은 xiaoming과 Dog가 관련이 있다고 할 수 있다. 물론 xiaoming은 여러 개의 Dog를 끌 수 있다.

어떻게 대상을 연결합니까


runtime가 제공하는 방법:
// 
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
// 
id objc_getAssociatedObject(id object, const void *key)
// 
void objc_removeAssociatedObjects(id object)

변수 설명:
id object: ( xiaoming)
const void *key: key, 
id value: ( dog)
objc_AssociationPolicy policy: 

objc_AssociationPolicy policy의 enum 값은 다음과 같습니다.
OBJC_ASSOCIATION_ASSIGN = 0,          
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, 
OBJC_ASSOCIATION_COPY_NONATOMIC = 3,  
OBJC_ASSOCIATION_RETAIN = 01401,       
OBJC_ASSOCIATION_COPY = 01403   

객체가 해제되면 연관된 객체의 해제 여부가 이 정책에 따라 결정되며, 정책이 RETAIN/COPY인 경우 연관된 객체는 해제(release)되며, ASSIGN인 경우에는 해제되지 않습니다.주의해야 할 것은, 우리는removeAssociated를 주동적으로 호출해서 관련 대상을 접촉할 필요가 없고, 지정한 대상을 해제할 필요가 있으면 setassociatedObject를nil로 설정하여 실현할 수 있다.

연관된 객체의 응용


1. 공통 속성 추가
이것은 가장 자주 사용하는 모델이다. 일반적으로 우리는 클래스 성명에 속성을 추가하지만 특정한 수요(예를 들어 앞에서 설명한 경우)에서 분류에 하나 이상의 속성을 추가해야 하면 컴파일러가 오류를 보고한다. 이 문제의 해결 방안은runtime의 관련 대상을 사용하는 것이다.응용 예: 우리는tabbar를 사용자 정의하고 공공의 속성과 방법을 노출해야 한다.(독자들은 계승과 분류로 이루어진 장점과 부족한 점을 생각할 수 있다)
@interface UITabBarController (Custom)

@property (nonatomic, strong) SUCustomTabbar * customTabbar;

@end
#import "UITabBarController+Custom.h"
#import 

@implementation UITabBarController (Custom)

- (void)setCustomTabbar:(UIView *)customTabbar {
    // key
    objc_setAssociatedObject(self, @selector(customTabbar), customTabbar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIView *)customTabbar {
    return objc_getAssociatedObject(self, @selector(customTabbar));
}

// ...

@end

이렇게 하면 우리는 원래의 tabbar처럼 사용자 정의 tabbar를 사용할 수 있다.
[self.tabBarController.customTabbar doSomgthig];

2. 개인 구성원 변수 추가
때때로 분류에 공공 성명에 노출되고 싶지 않은 구성원 변수를 추가해야 한다.응용 예: 버튼에 클릭 시간의 리셋을 추가합니다
@interface UIButton (Callback)

- (instancetype)initWithFrame:(CGRect)frame callback:(void (^)(UIButton *))callbackBlock;

@end
@interface UIButton ()

@property (nonatomic, copy) void (^callbackBlock)(UIButton * button);

@end

@implementation UIButton (Callback)

- (void (^)(UIButton *))callbackBlock {
    return objc_getAssociatedObject(self, @selector(callbackBlock));
}

- (void)setCallbackBlock:(void (^)(UIButton *))callbackBlock {
    objc_setAssociatedObject(self, @selector(callbackBlock), callbackBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (instancetype)initWithFrame:(CGRect)frame callback:(void (^)(UIButton *))callbackBlock {
    
    if (self = [super initWithFrame:frame]) {
        self.callbackBlock = callbackBlock;
        [self addTarget:self action:@selector(didClickAction:) forControlEvents:UIControlEventTouchUpInside];
    }
    return self;
}

- (void)didClickAction:(UIButton *)button {
    self.callbackBlock(button);
}

@end

독자 사고: 상기 코드에 메모리 관리 문제가 존재할 수 있는지
3. 관련 KVO 관찰자는 때때로 우리가 분류에서 KVO를 사용하는데 관련 대상을 관찰자로 사용하고 대상이 자신을 관찰하는 것을 최대한 피한다.이 응용 모델은 더 이상 예를 들지 않고 관심 있는 독자들은 스스로 깊이 연구하거나 코드를 평론에 붙일 수 있다.

사색


1. 관련 대상이 더 많은 응용 모델?2. 관련 대상이 문제 해결의 첫 번째 선택입니까?3. 관련 대상의 부작용?
여러분의 교류와 토론을 환영합니다.

좋은 웹페이지 즐겨찾기