ios - 拦截子类中的 Objective-C 委托(delegate)消息

标签 ios objective-c objective-c-runtime

我有一个 UIScrollView 的子类,我需要在其中对滚动行为做出内部响应。然而,viewcontroller 仍然需要监听滚动委托(delegate)回调,所以我不能在我的组件中直接窃取委托(delegate)。

有没有办法保留名为“delegate”的属性并只听取沿它发送的消息,或者以某种方式在内部劫持 delegate 属性并在运行一些代码后向外转发消息?

最佳答案

为避免手动覆盖所有委托(delegate)方法,您可以使用消息转发。我只是使用中间代理类实现了同样的事情,如下所示:

MessageInterceptor.h

@interface MessageInterceptor : NSObject {
    id receiver;
    id middleMan;
}
@property (nonatomic, assign) id receiver;
@property (nonatomic, assign) id middleMan;
@end

MessageInterceptor.m

@implementation MessageInterceptor
@synthesize receiver;
@synthesize middleMan;

- (id)forwardingTargetForSelector:(SEL)aSelector {
    if ([middleMan respondsToSelector:aSelector]) { return middleMan; }
    if ([receiver respondsToSelector:aSelector]) { return receiver; }
    return [super forwardingTargetForSelector:aSelector];
}

- (BOOL)respondsToSelector:(SEL)aSelector {
    if ([middleMan respondsToSelector:aSelector]) { return YES; }
    if ([receiver respondsToSelector:aSelector]) { return YES; }
    return [super respondsToSelector:aSelector];
}

@end

MyScrollView.h

#import "MessageInterceptor.h"

@interface MyScrollView : UIScrollView {
    MessageInterceptor * delegate_interceptor;
    //...
}

//...

@end

MyScrollView.m(已编辑,感谢 jhabbott):

@implementation MyScrollView

- (id)delegate { return delegate_interceptor.receiver; }

- (void)setDelegate:(id)newDelegate {
    [super setDelegate:nil];
    [delegate_interceptor setReceiver:newDelegate];
    [super setDelegate:(id)delegate_interceptor];
}

- (id)init* {
    //...
    delegate_interceptor = [[MessageInterceptor alloc] init];
    [delegate_interceptor setMiddleMan:self];
    [super setDelegate:(id)delegate_interceptor];
    //...
}

- (void)dealloc {
    //...
    [delegate_interceptor release];
    //...
}

// delegate method override:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    // 1. your custom code goes here
    // 2. forward to the delegate as usual
    if ([self.delegate respondsToSelector:@selector(scrollViewDidScroll:)]) {
        [self.delegate scrollViewDidScroll:scrollView];
    }
}

@end

使用这种方法,MessageInterceptor 对象会自动将所有委托(delegate)消息转发到常规委托(delegate)对象,除了您在自定义子类中覆盖的消息。 p>

关于ios - 拦截子类中的 Objective-C 委托(delegate)消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3498158/

相关文章:

ios - 为数组中对象的 iVar 赋值

objective-c - 如何解释 objective-c 类型说明符(例如,由 method_copyReturnType() 返回)?

javascript - 在 Objective-C 中更改 Javascript 变量

iphone - 如何将 UIActivityIndi​​catorView 与文本(UILabel)一起居中?

ios - 廉价鲨鱼 API : reading NSDictionary without a key

ios - 将@propertys 添加到核心数据类

ios - 我们如何在 Objective C 中添加文本字段来推送通知?

ios - 无法从数组中删除元素

ios - 如何以美国风格格式化恰好是电话号码的 UITextfield 文本?

objective-c - 获取调用方法的对象