Dru*_*erB 4 cocoa-touch delegates objective-c uiscrollview ios
我想实现一个UIScrollView
子类来呈现一些自定义格式化的内容.我只是设置滚动视图的模型对象属性,它处理所有必需的布局和渲染以显示内容.
这很好,但现在我想包括缩放.根据文档,为了支持缩放,您必须设置委托并实现该viewForZoomingInScrollView:
方法.我想我可以将委托设置为滚动视图本身并在子类中实现该方法.但这样做我将失去拥有外部委托(如封装UIViewController)的能力,可以通知滚动事件.
假设文档是正确的,并且绝对没有(记录)方法在没有代理的情况下实现缩放,我怎么还能保留定期,无关委托的可能性?
基于H2CO3建议保存指向真实委托的隐藏指针并将所有传入消息转发给它,我想出了以下解决方案.
声明一个私有委托变量来存储对传递给setDelegate:
方法的"真实"委托的引用:
@interface BFWaveScrollView ()
@property (nonatomic, weak) id<UIScrollViewDelegate> ownDelegate;
@end
Run Code Online (Sandbox Code Playgroud)
将委托设置为self以收到有关滚动事件的通知.使用super
,所以setDelegate:
调用原始实现,而不是我们修改过的实现.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[super setDelegate:self];
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
覆盖setDelegate:
以保存对"真实"委托的引用.
- (void)setDelegate:(id<UIScrollViewDelegate>)delegate {
_ownDelegate = delegate;
}
Run Code Online (Sandbox Code Playgroud)
当UIScrollView尝试调用其委托的方法时,它将首先检查是否委托respondsToSelector:
.如果选择器是UIScrollViewDelegate
协议的一部分,我们必须将它转发给真正的委托(不要忘记#import <objc/runtime.h>
).
- (BOOL)selectorIsScrollViewDelegateMethod:(SEL)selector {
Protocol *protocol = objc_getProtocol("UIScrollViewDelegate");
struct objc_method_description description = protocol_getMethodDescription(
protocol, selector, NO, YES);
return (description.name != NULL);
}
- (BOOL)respondsToSelector:(SEL)selector {
if ([self selectorIsScrollViewDelegateMethod:selector]) {
return [_ownDelegate respondsToSelector:selector] ||
[super respondsToSelector:selector];
}
return [super respondsToSelector:selector];
}
Run Code Online (Sandbox Code Playgroud)
最后,将所有委托方法转发给未在子类中实现的真实委托:
- (id)forwardingTargetForSelector:(SEL)selector {
if ([self selectorIsScrollViewDelegateMethod:selector]) {
return _ownDelegate;
}
return [super forwardingTargetForSelector:selector];
}
Run Code Online (Sandbox Code Playgroud)
不要忘记手动转发由子类实现的那些委托方法.
归档时间: |
|
查看次数: |
742 次 |
最近记录: |