iOS 에서 Runtime 의 몇 가지 기본 용법 기록
런 타임 구현 에 대한 세부 사항 을 소개 하 는 글 이 아니 라 오 브 젝 티 브-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)방법 교환 방법 SwizzlingObjective-C 는 동적 교체 방법 이나 인 스 턴 스 방법 에 사용 할 API 를 제공 합 니 다.
사용 사례
//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;
}
총결산이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Swift의 패스트 패스Objective-C를 대체하기 위해 만들어졌지만 Xcode는 Objective-C 런타임 라이브러리를 사용하기 때문에 Swift와 함께 C, C++ 및 Objective-C를 컴파일할 수 있습니다. Xcode는 S...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.