Кто-нибудь добился успеха с NSProxy из UIView (например, UILabel?)

я экспериментирую, добавляя функциональные возможности своим UIView (настраивая CALayers в соответствии с состоянием), настраивая подкласс NSProxy для замены любого UIView, который я выберу. Вот что я пробовал:

В моем подклассе 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

Я могу проверить, что каждый из методов до -superlayer вызывается успешно при использовании NSProxy. По какой-то причине с NSProxy суперуровень в UILabel вызывается вместо CALayer. Возможно, где-то что-то запутается и UILabel вставлен в подслои вместо своего CALayer?

Я что-то упускаю?

Выполняет ли UIKit какие-то оптимизации, которые обходят обычный механизм, в который подключается NSProxy?

Другое мысли?

Спасибо!

Генри

PS Я пробовал это только в Симуляторе, а не на устройстве. Будет ли это поведение по-другому?

13
задан henryaz 21 February 2011 в 00:35
поделиться