我正在尝试通过设置一个 NSProxy 子类来代替我选择的任何 UIView 来向我的 UIViews 添加功能(根据状态配置 CALayers)。这是我尝试过的:
在我的 NSProxy 子类中,我有以下代码:
#pragma mark Initialization / Dealloc
- (id)initWithView:(UIView *)view
{
delegate = view;
[delegate retain];
return self;
}
- (void)dealloc
{
[delegate release];
[super dealloc];
}
#pragma mark Proxy Methods
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
[anInvocation setTarget:delegate];
[anInvocation invoke];
return;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
return [delegate methodSignatureForSelector:aSelector];
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
BOOL rv = NO;
if ([delegate respondsToSelector:aSelector]) { rv = YES; }
return rv;
}
而且,以这种方式使用我的 NSProxy 子类:
UILabel *label = [[HFMultiStateProxy alloc] initWithView:[[[UILabel alloc] initWithFrame:cellFrame] autorelease]];
label.text = text;
label.font = font;
label.textAlignment = UITextAlignmentCenter;
label.backgroundColor = [UIColor clearColor];
label.opaque = NO;
[self addSubview:label];
似乎可以工作,直到我点击 addSubview: 行。
打开消息跟踪 (instrumentObjcMessageSends(YES); ) 显示之前每个消息的转发工作,直到 addSubview: 的深处,这一系列方法调用显示在日志中(此处显示的第一条消息是通过代理):
- UILabel UIView _makeSubtreePerformSelector:withObject:
- UILabel UIView _makeSubtreePerformSelector:withObject:withObject:copySublayers:
- CALayer CALayer sublayers
- NSMethodSignature NSMethodSignature methodReturnType
- NSMethodSignature NSMethodSignature _argInfo:
- NSMethodSignature NSMethodSignature _frameDescriptor
+ UILabel NSObject resolveInstanceMethod:
- UILabel NSObject forwardingTargetForSelector:
- UILabel NSObject forwardingTargetForSelector:
- UILabel NSObject methodSignatureForSelector:
- UILabel NSObject methodSignatureForSelector:
- UILabel NSObject class
- UILabel NSObject doesNotRecognizeSelector:
我收到以下错误:
2011-02-20 16:38:52.048 FlashClass_dbg[22035:207] -[UILabel superlayer]: unrecognized selector sent to instance 0x757d470
如果我不使用 NSProxy 子类而是使用 UILabel 子类(HFMultiStateLabel),它可以正常工作。这是调用 addSubview: 后发生的消息跟踪(HFNoteNameControl 是标签的父视图):
- HFNoteNameControl UIView addSubview:
- HFNoteNameControl UIView _addSubview:positioned:relativeTo:
- HFMultiStateLabel UIView superview
- HFMultiStateLabel UIView window
- HFNoteNameControl NSObject isKindOfClass:
- HFNoteNameControl NSObject class
- HFNoteNameControl UIView window
- UIWindow NSObject isKindOfClass:
- UIWindow NSObject class
- HFNoteNameControl UIView _shouldTryPromoteDescendantToFirstResponder
- HFMultiStateLabel UIView _isAncestorOfFirstResponder
- HFMultiStateLabel UIView _willMoveToWindow:withAncestorView:
- HFMultiStateLabel UIView _willMoveToWindow:
- HFMultiStateLabel UIView willMoveToWindow:
- HFMultiStateLabel UIView _makeSubtreePerformSelector:withObject:withObject:copySublayers:
- CALayer CALayer sublayers
- HFMultiStateLabel UIView willMoveToSuperview:
- HFMultiStateLabel UIView _unsubscribeToScrollNotificationsIfNecessary:
- HFMultiStateLabel UIView _makeSubtreePerformSelector:withObject:
- HFMultiStateLabel UIView _makeSubtreePerformSelector:withObject:withObject:copySublayers:
- CALayer CALayer sublayers
- CALayer CALayer superlayer
我可以验证使用 NSProxy 时,直到 -superlayer 之前的每个方法都被成功调用。出于某种原因,使用 NSProxy,UILabel 上的 superlayer 被调用而不是 CALayer。也许某处有些东西变得混乱并且 UILabel 被插入到子层而不是它的 CALayer 中?
我错过了什么吗?
UIKit 是否进行了某种绕过 NSProxy 挂钩的正常机制的优化?
其他想法?
谢谢!
亨利
PS我只在模拟器中试过这个,而不是设备。这种行为会有什么不同吗?