iphone – 任何有成功的UIView的NSProxy(例如,UILabel?)

我正在尝试通过设置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上的超层被调用而不是CALayer.也许某事会让人困惑,UILabel被插入子层而不是其CALayer?

我错过了什么吗?

UIKit是否做了一些优化,绕过NSProxy钩入的正常机制?

其他想法?

谢谢!

亨利

PS我只是在模拟器中尝试过,而不是设备.这种行为会有什么不同吗?

我试图解决相同的问题 – 当我遇到这个问题时,使用NIVroxy与UIView(在我的情况下是UITableViewCell).我将所有呼叫记录到控制台:

...
App[2857:c07] MyHeaderCell: --- method signature for: _unsubscribeToScrollNotificationsIfNecessary:
App[2857:c07] MyHeaderCell: --- _unsubscribeToScrollNotificationsIfNecessary:
App[2857:c07] MyHeaderCell: --- method signature for: _makeSubtreePerformSelector:withObject:
App[2857:c07] MyHeaderCell: --- _makeSubtreePerformSelector:withObject:
App[2857:c07] +[MyHeaderCell superlayer]: unrecognized selector sent to class 0x1331f8c
App[2857:c07] CRASH: +[SMSHeaderCell superlayer]: unrecognized selector sent to class 0x1331f8c
App[2857:c07] Stack Trace:...

它在无法识别的选择器异常时崩溃.

通常,该对象首先被询问为 – (NSMethodSignature *)methodSignatureForSelector:(SEL)sel方法,当返回时,它调用代理中的 – (void)forwardInvocation:(NSInvocation *)调用.这样我们可以重定向消息.如果没有返回NSMethodSignature,则会在对象上调用didNotRecognizeSelector:方法.所以我们得到甚至无法识别的选择器调用.

这种方法适用于实例方法,但是这种崩溃是由一个类方法引起的,我们没有权力 – 对象本身不被调用(类是).我想强制运行时调用我的代理类,即使是通过覆盖我的NSProxy子类的getter的类方法

- (Class) class
{
    return _myRealClass;
}

哪个没有工作.所以NSProxy不足以做到这一点.现在我试图使用NSObject而不是NSProxy来实现所有所需的行为,并且由于NSObject具有可能有用的(BOOL)resolveClassMethod(SEL)sel方法.我会编辑这篇文章,一旦我发现NSObject更适合这个.

//编辑

似乎问题是,使用NSProxy,超级层在UIView而不是CALayer被调用.证明:http://t2523.codeinpro.us/q/508112244f1eba38a4fb032e

所以这真的好像是一个UIKit快捷方式的问题 – 他们不会发送一个常规的消息调用(速度优化我会猜测).

无论如何,我正在寻找一种解决这个问题的方法.

翻译自:https://stackoverflow.com/questions/5061223/anybody-successful-with-nsproxy-of-uiview-e-g-uilabel

转载注明原文:iphone – 任何有成功的UIView的NSProxy(例如,UILabel?)