消息转发,适用于把操作给另外一个类来实现
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];
if (!signature) {
signature = [self.displayLabel methodSignatureForSelector:aSelector];
}
return signature;
}
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
SEL selector = [anInvocation selector];
if ([self.displayLabel respondsToSelector:selector]) {
[anInvocation invokeWithTarget:self.displayLabel];
}
}
下面例子中,一个UIViewController包含了UIlable 属性 displayLabel, 如果UIViewController 实例调用[instance setText:@"string"]方法,由于类没有实现setText:方法,通过上面两行代码,将会转发,由 displayLabel 实现。
#import "RootVC.h"
@interface RootVC ()
@end
@implementation RootVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = @"Root";
[self addButton];
// Do any additional setup after loading the view.
}
-(void)addButton
{
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(20.0, 100.0, 100.0, 40.0);
[btn setTitle:@"Next" forState:UIControlStateNormal];
[btn setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
[btn addTarget:self action:@selector(naviNext) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(20.0, 140.0, 200.0, 30.0)];
self.displayLabel = label;
[self.view addSubview:label];
[label release];
[self setText:@"你好"]; //这里setText是不能被自己接受的,但是应为在下面做了消息转发,最后事件由self.displayLabel 接受了
}
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];
if (!signature) {
signature = [self.displayLabel methodSignatureForSelector:aSelector];
}
return signature;
}
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
SEL selector = [anInvocation selector];
if ([self.displayLabel respondsToSelector:selector]) {
[anInvocation invokeWithTarget:self.displayLabel];
}
}
-(void)naviNext
{
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
下面是封装的分类
//
// TestController.m
// 0803test
//
// Created by Xudongdong on 2017/8/29.
// Copyright © 2017年 Xudongdong. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSNull (InternalNullExtention)
@end
//
// TestController.m
// 0803test
//
// Created by Xudongdong on 2017/8/29.
// Copyright © 2017年 Xudongdong. All rights reserved.
//
//来源于 http://blog.rpplusplus.me/blog/2014/03/28/nsnull-category/
#define NSNullObjects @[@"",@0,@{},@[]]
#import "NSNull+InternalNullExtention.h"
@implementation NSNull (InternalNullExtention)
- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature* signature = [super methodSignatureForSelector:selector];
if (!signature) {
for (NSObject *object in NSNullObjects) {
signature = [object methodSignatureForSelector:selector];
if (signature) {
break;
}
}
}
return signature;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
SEL aSelector = [anInvocation selector];
for (NSObject *object in NSNullObjects) {
if ([object respondsToSelector:aSelector]) {
[anInvocation invokeWithTarget:object];
return;
}
}
[self doesNotRecognizeSelector:aSelector];
}
@end
网友评论