Вопрос по cocoa-touch, cocoa, objective-c, ios – Shared UITableViewDelegate

6

Я пишу подкласс UITableView, и я хочу, чтобы мой подкласс сам обрабатывал некоторые из методов UITableViewDelegate, прежде чем передавать их в «реальный» тип. делегировать, а также переслать все методы UITableViewDelegate, не реализованные моим подклассом.

В подклассе у меня есть частная собственность:

@property (nonatomic, assign) id <UITableViewDelegate> trueDelegate;

который содержит «реальный делегат» что все неосуществленные методы должны быть направлены вперед. В обоих моих методах инициализации я установил

self.delegate = self;

и я переопределить - (void) setDelegate: (id) вот так

-(void)setDelegate:(id<UITableViewDelegate>)delegate {
    if (delegate != self) {
        _trueDelegate = delegate;
    } else {
        [super setDelegate:self];
    }
}

Затем я переопределяю их для обработки пересылки сообщений.

-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    NSMethodSignature *sig;
    sig = [[self.delegate class] instanceMethodSignatureForSelector:aSelector];
    if (sig == nil) {
        sig = [NSMethodSignature signatureWithObjCTypes:"@^v^c"];
    }
    return sig;
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    SEL selector = anInvocation.selector;
    if ([self respondsToSelector:selector]) {
        [anInvocation invokeWithTarget:self];
    } else {
        [anInvocation invokeWithTarget:_trueDelegate];
    }
}

Проблема заключается в том, что нереализованные методы делегата никогда не вызываются в табличном представлении, поэтому им не дают возможности быть переданными вместе с объектом _trueDelegate.

Я попытался проверить их здесь:

- (BOOL)respondsToSelector:(SEL)aSelector {

}

но этот метод никогда не вызывается для методов UITableViewDelegate, хотя он отлично ловит другие методы.

Вы объявили свой расширенный класс как соответствующий протоколам делегатов? Chris Trahey
Я спрашиваю, потому что возможно, что tableView используетconformsToProtocol: вместоrespondsToSelector: при вызове методов делегата. Chris Trahey
Действительно, я понял, что это может быть проблемой, я проверю это Lance

Ваш Ответ

1   ответ
12

UITableView проверяет и запоминает, какие методы делегата доступны, как только делегат установлен. Вы устанавливаете делегатаself сначала, потомtrueDelegate, Таким образом, в то время как делегат установлен наUITableView, trueDelegate являетсяnil, так что-respondsToSelector: на что всегда возвращаетсяNO.

Чтобы это исправить, установите делегат послеtrueDelegate установлено. Также вы можете упростить код пересылки. Удалите весь код, указанный выше, за исключением свойства и замените его следующим:

- (void)setDelegate:(id <UITableViewDelegate>)delegate
{
    if (delegate == self) return;

    self.trueDelegate = delegate;
    [super setDelegate:self];
}

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

    return [self.trueDelegate respondsToSelector:aSelector];
}

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return self.trueDelegate;
}
Обалденный ответ, перепробовал все, пока не получил вашу подсказку.
@TammoFreese, знаете ли вы, есть ли какая-либо документация, или пишите дальше в кеш таблиц фактов? функциональные ответы?
@NikitaIvaniushchenko Рад, что я мог помочь!
Спасибо! Это прекрасно, просто любопытно, как вы узнали об упомянутой оптимизации UITableView? Lance
Некоторое время назад я наткнулся на это, когда смотрел на правильное направление работы делегатов._tableFlags вUITableView.h дать довольно хороший намек, чтоUITableView кэширует, какие методы реализованы в его делегате / источнике данных.

Похожие вопросы