iOS 메시지 전달 메커니즘
하나의 방법의 실현은 반드시 세 가지 부분을 포함한다. 그것이 바로 집행 방법의 대상, 방법의 명칭, 불확정한 매개 변수이다.
SEL은 방법의 이름일 뿐이고 내부의imp가 진정한 실현 코드이다
메시지를 보내는 것은
objc_send(id, SEL, ...)
를 통해 이루어진다. 먼저 대상의 클래스 대상cache
, methodlist
및 부류 대상cache
, methodlist
에서 순서대로 SEL
에 대응하는IMP
를 찾는다.동적 방법을 찾지 못하고 실현되면 결의 메커니즘이 결의된다메시지의 발송 원리를 이해한 토대에서 메시지 전달 메커니즘이 있다.
만약에 대상이 그 자체가 실현되지 않은 방법을 호출하면 컴파일할 때 경고가 나타나고 직접 실행하면crash, 즉 붕괴된다. 붕괴되는 원인은 메시지가 처리할 수 없는 대상에게 발송되기 때문이다. 왜냐하면 OC는 실행할 때 언어이기 때문에 실행 기간에 뭔가를 할 수 있기 때문이다. 이때 오류 보고를 해결하고 이 방법을 정상적으로 호출하기 위해서는 메시지 전송 메커니즘으로 처리해야 한다.일반적으로 세 개의 리시버 맨이라고 부른다.
1. 동적 방법 해석, 즉 +(BOOL)resolveInstanceMethod: (SEL)sel과
+ (BOOL)resolveClassMethod: (SEL)sel 두 가지 방법으로 처리할 수 없는 대상 방법과 클래스 방법에 대응한다.동적 추가 방법의 실현을 실현할 수 있다. 본 클래스에 추가 방법을 써서 매개 변수sel이 호출된 방법인지 판단할 수 있다. 만약에 호출된 방법을 추가 쓰기 방법으로 바꾸면 이 방법명을 호출하여 그 방법체의 효과를 실현할 수 있다.
2. 지원 수신자 단계, 즉 - (id) forwarding Target For Selector: (SEL)a Selector. 만약에 다른 클래스에서 본 클래스에서 호출된 동일한 이름을 성명하고 실현하는 방법이 있다면 이 지원 단계에서 다른 클래스의 대상이 응답할 수 있는지 판단할 수 있고 할 수 있다면 그 대상에게 방법을 맡겨 처리할 수 있으며 이 방법에서 방법을 한 대상에게 전달하여 처리할 수 있다.
3. 완전한 메시지 전달 단계, 즉 - (void) forwardInvocation: (NSInvocation*) anInvocation. 이 방법은 방법의 실현을 여러 대상에게 전달할 수 있고 효과는 다중 계승과 유사하다.
주의해야 할 것은 이 방법을 실현하기 전에 다시 써야 한다는 것이다
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
, 이 방법에서 대응 처리를 한다.
4. 위 세 가지 방법 모두 이 메시지를 처리하지 못하면 NSObject에 들어갑니다
- (void)doesNotRecognizeSelector: (SEL)aSelector에서 이상을 던지고 NSObject 분류에서 이 방법을 다시 쓰는 것을 권장하지 않습니다. 이 방법은 이상을 던지는 처리 작업과 관련이 있습니다.
총괄: 한 함수를 찾을 수 없을 때 OC는 세 가지 방법을 제공했다. 첫째, Resolve Instance Method를 호출하여 클래스에 이 함수를 추가할 기회를 준다. 둘째, forwarding Target ForSelector를 호출하여 다른 대상에게 이 함수를 실행하게 한다. 셋째, forward Invocation(함수 집행기)를 호출하여 목표 함수를 다른 형식으로 유연하게 집행한다.
모두 맞지 않으면 DoesNotRecognizeSelector를 호출하여 이상을 던집니다.
의문
Q1: 그럼 우리 마지막 리시버 맨만 쓰면 얼마나 좋을까, 왜 앞의 두 개가 더 필요할까?사실은 이 세 가지 방법의 용도와 다르다. 운행 기간에 방법을 추가하고 1을 사용한다.다른 대상에게 전달하고 방법을 바꿀 때 2를 사용한다.여러 대상에게 전달해야 할 때 3을 사용한다.
그리고 절차가 뒤로 갈수록 메시지 처리의 대가가 커지고 마지막 단계가 되면 NSInvocation 대상이 만들어진다.
Q2: 메시지 전달에는 어떤 앱 장면이 있나요?운행 기간에 어떤 방법을 추가할 수 있다. 예를 들어 Teacher류에는 팀 방법이 있고 Drug Dealer류에는 lets Cook 방법이 있다. 1번 리시버 방법을 통해 우리는 운행 기간에 Sale Drug를 팀버에 몰래 추가하는 방법 목록에 팀버가 마약 판매 기능을 갖추도록 할 수 있다. [팀버 guess What HeDo]는 실제 사용한 것은 [팀버 lets Cook]이다. 아이고, 절명독사야.
방법을 다른 대상에게 넘기고 예를 들면 테처류(블로거와 선생님이 원한이 있나...),[teacher letsCook], 대상을 운행 기간에 drugDealer로 바꿀 수 있습니다.쿡류 하나 더 주세요. lets 쿡 방법도 있는데 이번에는 쿡 마약이 아니라 쿡 요리예요.따라서 [teacher letsCook]을 통해 [drugDealer letsCook]을 실현할 수도 있고 [cook letsCook]을 실현할 수도 있다.OC가 다중 승계를 이룬 셈인데 좀 부적절하지만...
코드 예:
#import "ViewController.h"
#import "objc/runtime.h"
#import "Person.h"
void dynamicMethodIMP(id self, SEL _cmd) {
NSLog(@" >> dynamicMethodIMP");
}
@interface ViewController ()
@property (nonatomic, strong) Person *person;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.person = [[Person alloc] init];
[self learn];
}
//+(BOOL)resolveInstanceMethod:(SEL)sel {
// if (sel == @selector(learn)) {
// class_addMethod([self class], sel, (IMP) dynamicMethodIMP, "v@:");
// return YES;
// }
// return [super resolveInstanceMethod:sel];
//}
/**
@param aSelector
@return self\ nil ,
*/
//-(id)forwardingTargetForSelector:(SEL)aSelector {
//
// if ([self.person respondsToSelector:aSelector]) {
// return self.person;
// }
// return [super forwardingTargetForSelector:aSelector];
//}
-(void)forwardInvocation:(NSInvocation *)anInvocation {
SEL invocation = [anInvocation selector];
if ([self.person respondsToSelector:invocation]) {
[anInvocation invokeWithTarget:self.person];
}
}
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
NSMethodSignature* signature = [super methodSignatureForSelector:aSelector];
if (!signature) {
signature = [self.person methodSignatureForSelector:aSelector];
}
return signature;
}
//-(void)doesNotRecognizeSelector:(SEL)aSelector {
// [super doesNotRecognizeSelector:aSelector];
//}
@end
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 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에 따라 라이센스가 부여됩니다.