简单来说,就是在Objective-C中,使用对象进行方法调用是一个消息发送的过程(Objective-C采用“动态绑定机制”,所以所要调用的方法直到运行期才能确定)。
方法在调用时,系统会查看这个对象能否接收这个消息(查看这个类有没有这个方法,或者有没有实现这个方法。),如果不能并且只在不能的情况下,就会调用下面这几个方法,给你“补救”的机会,你可以先理解为几套防止程序crash的备选方案,我们就是利用这几个方案进行消息转发,注意一点,前一套方案实现后,后一套方法就不会执行。如果这几套方案你都没有做处理,那么程序就会报错crash
+ (BOOL)resolveInstanceMethod:(SEL)sel + (BOOL)resolveClassMethod:(SEL)sel
- (id)forwardingTargetForSelector:(SEL)aSelector
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector; - (void)forwardInvocation:(NSInvocation *)anInvocation;
`
具体的看下面这篇文章就可以了:
http://my.oschina.net/Jacedy/blog/625343
这是本文的重点,主要讲下消息转发机制在实际中的使用场景,发现网上关于这方面的讲解还是比较少。
我们自定义了一个SGScrollview,继承自系统的UITableView,然后把SGScrollview添加到ViewController上面。要求在SGScrollview内部监听scrollview的代理事件做一些处理,同时在viewcontroller上也要监听scrollview的代理事件做处理,保证他们不会冲突和覆盖。
如果按照传统的做法,我们把SGScrollview的代理设置为viewcontroller,那么这个时候scrollViewWillBeginDragging方法只会被viewcontroller监听到,而在SGScrollview内部的    scrollViewWillBeginDragging
方法就失效了。  
反之如果在SGScrollview设置代理为自己,那么viewcontroller的代理方法监听也会失效。
我们无法同时在两个不同的类里面监听同一个父类(UIScrollview)的代理方法,为了解决这个问题,我们可以用runtime的消息转发机制,建立一个代理转发类,让它来负责把代理方法的消息发送给不同的消息接受者。
下面直接上代码
#import <Foundation/Foundation.h>
@interface MessageInterceptor : NSObject
@property (nonatomic, assign) id receiver;
@property (nonatomic, assign) id middleMan;
@end
====================================
#import "MessageInterceptor.h"
@implementation MessageInterceptor
- (id)forwardingTargetForSelector:(SEL)aSelector {
    if ([self.middleMan respondsToSelector:aSelector]) {
        return self.middleMan;
    }
    if ([self.receiver respondsToSelector:aSelector]) {
        return self.receiver;
    }
    return [super forwardingTargetForSelector:aSelector];
}
- (BOOL)respondsToSelector:(SEL)aSelector {
    if ([self.middleMan respondsToSelector:aSelector])
    {
        return YES;
    }
    if ([self.receiver respondsToSelector:aSelector])
    {
        return YES;
    }
    return [super respondsToSelector:aSelector];
}
@end
  #import <UIKit/UIKit.h>
#import "MessageInterceptor.h"
@interface SGScrollview : UITableView<UITableViewDelegate>
@property(nonatomic,strong)MessageInterceptor *delegate_interceptor;
@end
===================
#import "SGScrollview.h"
@implementation SGScrollview
-(instancetype)initWithFrame:(CGRect)frame{
    if (self == [super initWithFrame:frame]) {
        self.delegate_interceptor = [[MessageInterceptor alloc] init];
        self.delegate_interceptor.middleMan = self;
        [super setDelegate:(id)self.delegate_interceptor];    }
    return self;
}
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    NSLog(@"%s的方法被调用",__PRETTY_FUNCTION__);
    if ([self.delegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]) {
        [self.delegate scrollViewWillBeginDragging:scrollView];
    }
}
- (id)delegate
{
    return self.delegate_interceptor.receiver;
}
- (void)setDelegate:(id)newDelegate {
    [super setDelegate:nil];
    self.delegate_interceptor.receiver = newDelegate;
    [super setDelegate:(id)self.delegate_interceptor];
}
@end
  #import "ViewController.h"
#import <objc/message.h>
#import "SGScrollview.h"
@interface ViewController ()<UIScrollViewDelegate,UITableViewDataSource,UITableViewDelegate>
@end
@implementation ViewController
-(void)viewDidLoad{
    [super viewDidLoad];
    SGScrollview *SV = [[SGScrollview alloc]initWithFrame:self.view.bounds];
    SV.dataSource = self;
    SV.delegate =self;
    [self.view addSubview:SV];
     [SV registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return 20;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    cell.textLabel.text = [NSString stringWithFormat:@"%zd",indexPath.row];
    return cell;
}
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    NSLog(@"%s的方法被调用",__PRETTY_FUNCTION__);
}
@end
  此时拖动tableview,输出如下:
2016-08-12 13:31:09.579 test1[4474:410866] -[SGScrollview scrollViewWillBeginDragging:]的方法被调用 2016-08-12 13:31:11.630 test1[4474:410866] -[ViewController scrollViewWillBeginDragging:]的方法被调用
可以看到两个类都可以监听到代理方法。
Demo下载地址