Skip to content

Latest commit

 

History

History
102 lines (82 loc) · 2.67 KB

xiaoxizhuanfa.md

File metadata and controls

102 lines (82 loc) · 2.67 KB

消息转发

  1. 首先查找系统的cache中是否有该函数,没有的话则在classsuperclass中查找是否有该方法。
  2. 没有的话则进入动态解析,在这个函数中可以利用runtime添加未实现的方法。添加之后,系统又会重新回到步骤1
  3. 快速转发给- (id)forwardingTargetForSelector:(SEL)aSelector的返回值
  4. 慢速转发给- (void)forwardInvocation:(NSInvocation *)anInvocation,然后手动调用[anInvocation invoke].

1. 动态解析

+[resolveInstanceMethod:]中根据sel来动态添加方法。

+(BOOL)resolveInstanceMethod:(SEL)sel{
	NSLog(@"%s",__func__);

	if ([NSStringFromSelector(sel) isEqualToString: @"test"]) {
		Method m = class_getInstanceMethod(self.class, @selector(t));
		class_addMethod(self,
							sel,
							method_getImplementation(m),
							method_getTypeEncoding(m));
		return  YES;
	}
	return [super resolveInstanceMethod:sel];
}

2. 快速转发

转发给已经实现该selinstance或者class.

- (id)forwardingTargetForSelector:(SEL)aSelector{
	NSLog(@"%s",__func__);

	if (aSelector==@selector(test)) {
		return [ViewController alloc];
	}
	return [super forwardingTargetForSelector:aSelector];
}

3. 慢速转发

慢速转发会调用-[methodSignatureForSelector:]获取函数签名,然后用NSInvocation手动调用。

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
	NSLog(@"%s",__func__);

	if (aSelector == @selector(test)) {
		NSMethodSignature *sign=[NSMethodSignature signatureWithObjCTypes:"v16@0:8"];
		return  sign;
	}
	return [super methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation{
	anInvocation.selector=@selector(t);
	[anInvocation invoke];
}

4. NSTimer前引用self,使用NSProxy解决相互强引用

@implementation Proxy
- (instancetype)initWithTarget:(id)target {
	_target = target;
	return self;
}

//类方法
+ (instancetype)proxyWithTarget:(id)target {
	return [[self alloc] initWithTarget:target];
}

#pragma mark - over write

//重写NSProxy如下两个方法,在处理消息转发时,将消息转发给真正的Target处理
- (void)forwardInvocation:(NSInvocation *)invocation {
	[invocation invokeWithTarget:self.target];
}

//
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
	return [_target methodSignatureForSelector:selector];
}
- (void)dealloc
{
	NSLog(@"%s",__func__);
}


// 使用例子:
-(void)setTimer{
	Proxy *xy= [Proxy proxyWithTarget:self];

	timer=[NSTimer scheduledTimerWithTimeInterval:0.2
										   target:xy
										 selector:@selector(p)
										 userInfo:nil
										  repeats:YES];
}