Objective-C Method Swizzling
Method Swizzling은 OC
<objc/runtime.h>
라이브러리에서 제공하는'흑마법'중 하나다.예.
NSArray의 lastObject를 대체하는 방법의 예:
NSArray에서 lastObject를 교체해야 하는 방법 추가 – xxxlastObject 방법:
#import "NSArray+Swizzle.h"
@implementation NSArray (Swizzle)
- (id)xxx_lastObject
{
id ret = [self xxx_lastObject];
NSLog(@"********** myLastObject ***********");
return ret;
}
@end
여기 쓰는 법 주의, xxxlastObject 방법의 방법체에서 [self xxx lastObject]가 호출되었습니다. 이렇게 쓰면 귀속이 되지 않고 나중에 xxx 가 교환됩니다.lastObject와 lastObject의 IMP입니다. 사실 [self xxx lastObject]는 [self lastObject]를 실행합니다.
IMP 교체
#import <objc/runtime.h>
#import "NSArray+Swizzle.h"
Method ori_Method = class_getInstanceMethod([NSArray class], @selector(lastObject));
Method my_Method = class_getInstanceMethod([NSArray class], @selector(xxx_lastObject));
method_exchangeImplementations(ori_Method, my_Method);
여기에 도입
<objc/runtime.h>
이 필요합니다. 그렇지 않으면 오류가 발생합니다. runtime의method 를 사용했기 때문입니다.exchangeImplementations 방법.method_exchangeImplementations
로 xxx 스왑lastObject 및 lastObject의 IMP입니다.뒤이어 더욱 깊은 차원의 원리를 설명할 것이다.lastObject 호출 시도
#import <objc/runtime.h>
#import "NSArray+Swizzle.h"
NSArray *array = @[@"0",@"1",@"2",@"3"];
NSString *string = [array lastObject];
NSLog(@"TEST RESULT : %@",string);
출력 결과는 다음과 같습니다.
1
2
********** myLastObject *********** TEST RESULT : 3
분명히lastObject 방법을 호출하였는데, 사실은 우리가 추가한 xx 를 호출하였습니다lastObject 메서드.
쓸모
Method Swizzling은 매우 강력하며 주요 기능은 다음과 같습니다.
iOS 시스템 라이브러리나 제3자 라이브러리의 원본 코드를 수정하지 않은 토대에서 기존 호출 논리를 수정한다.
동적 추가, 수정 방법, 온라인 버그 복구공통 API
관련 상용 방법은 모두
<objc/runtime.h>
가방 안에 있다.// Method
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
// Method
IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
// 2 IMP
void method_exchangeImplementations(Method m1, Method m2)
//
Method class_getInstanceMethod(Class aClass, SEL aSelector);
밑바닥 원리
운행할 때 OC의 방법은
Method
라는 구조체로 이런 objc_method
유형의 구조체는 다음과 같이 정의된다.struct objc_method
SEL method_name OBJC2_UNAVAILABLE;
char *method_types OBJC2_UNAVAILABLE;
IMP method_imp OBJC2_UNAVAILABLE;
}
method_name는 방법의 selector로 실행할 때의 방법명으로 이해할 수 있습니다.
*method_types는 매개 변수와 반환값 형식을 인코딩하는 문자열입니다.
method_imp는 방법 실현을 가리키는 지침이다.
Method Swizzling , , 。
위 섹션에서 NSArray의 lastObject를 수정한 예를 들어 설명합니다.
처음에 lastObject 및 xxxlastObject 메서드의 Method 구조체:
Method lastObject {
SEL method_name = @selector(lastObject)
char *method_types = “v@:“ // void, id(self),selector(_cmd)
IMP method_imp = 0x000FFFF // ([NSArray lastObject])
}
Method xxx_lastObject {
SEL method_name = @selector(swizzle_originalMethodName)
char *method_types = “v@:”
IMP method_imp = 0x1234AABA // ([NSArray xxx_lastObject])
}
호출
void method_exchangeImplementations(Method m1, Method m2)
, 양자 교환의 실현: Method ori_Method = class_getInstanceMethod([NSArray class], @selector(lastObject));
Method my_Method = class_getInstanceMethod([NSArray class], @selector(xxx_lastObject));
method_exchangeImplementations(ori_Method, my_Method);
바뀐 Method 구조체:
Method lastObject {
SEL method_name = @selector(lastObject)
char *method_types = “@@:“ // id, id(self),selector(_cmd)
IMP method_imp = 0x1234AABA // ([NSArray xxx_lastObject])
}
Method xxx_lastObject {
SEL method_name = @selector(swizzle_originalMethodName)
char *method_types = “@@:”
IMP method_imp = 0x000FFFF // ([NSArray lastObject])
}
사용
void method_exchangeImplementations(Method m1, Method m2)
의 본질은 xxx 가 바뀌었다는 것을 알 수 있다lastObject와 lastObject의 IMP는 실행할 때 방법의 교체를 실현합니다.[array lastObject]를 실행할 때 [array xxx lastObject]를 실행하는 방법을 실행합니다.추가 팁
+load
Swizzling의 처리는 클래스
+load
방법에서 완성되었다.+load
방법은 클래스가 OC에 추가되었을 때 실행되고 한 번만 호출되기 때문에 Swizzling 방법의 신속한 처리를 보장합니다.dispatch_once
Swizzling의 처리
dispatch_once
에서 완료되었습니다.한 번만 집행할 것을 보증합니다.prefix
Swizzling 메서드는 메서드 이름 충돌을 방지하기 위해 접두어를 추가합니다.
코드 예
코드 예
참고 자료
Method Swizzling
How to swizzle a class method on iOS?
iOS 4.3: imp_implementationWithBlock()
Objective-C의 hook 프로젝트 (1): Method Swizzling
Objective-C에 대한 동적 힌트 및 팁
기사 출처:http://sjpsega.com/blog/2014/09/17/oc-method-swizzling/