Протоколы Objective-C в протоколах - PullRequest
1 голос
/ 30 октября 2009

Я недавно начал пробовать свои силы в использовании протоколов в моей разработке Objective-C в качестве (очевидного) средства более адекватного делегирования задач моим классам. Я полностью понимаю основные понятия протоколов и как они работают. Однако я наткнулся на препятствие при попытке создать собственный протокол, который, в свою очередь, реализует другой протокол. С тех пор я нашел решение, но мне любопытно, почему не работает следующее:

@protocol STPickerViewDelegate < UIPickerViewDelegate >

- ( void )customCallback;

@end

@interface STPickerView : UIPickerView
{
    id < STPickerViewDelegate > delegate;
}

@property ( nonatomic, assign ) id < STPickerViewDelegate > delegate;

@end

Затем в контроллере представления, который соответствует STPickerViewDelegate:

STPickerView * pickerView = [ [ STPickerView alloc ] init ];
pickerView.delegate = self;

- ( void )customCallback
{
    ...
}

- ( NSString * )pickerView:( UIPickerView * )pickerView titleForRow:( NSInteger )row forComponent:( NSInteger )component
{
    ...
}

Проблема была в том, что pickerView:titleForRow:forComponent: никогда не вызывали. С другой стороны, customCallback назывался просто отлично, что неудивительно. Я не понимаю, почему STPickerViewDelegate, который сам по себе соответствует UIPickerViewDelegate, не уведомляет мой контроллер представления о том, когда должны произойти события из UIPickerViewDelegate. Согласно моему пониманию документации Apple, если сам протокол (A) соответствует другому протоколу (B), то класс (C), который соответствует первому протоколу (A), должен также соответствовать второму протоколу (B), который именно то поведение, которое я хочу и ожидал.

В итоге я удалил свойство id< STPickerViewDelegate > delegate из STViewPicker и вместо этого сделал что-то подобное в моей реализации STViewPicker, где я хочу вызвать customCallback:

if ( [ self.delegate respondsToSelector:@selector( customCallback ) ] )
{
    [ self.delegate performSelector:@selector( customCallback ) ];
}

Это прекрасно работает, но я действительно озадачен, почему мой оригинальный подход не сработал.

Ответы [ 2 ]

3 голосов
/ 30 октября 2009

Проблема заключалась в том, что UIPickerView уже имеет переменную-член делегата, и вы объявляли другую в подклассе, который был тем, что устанавливалось, в то время как переменная-делегат суперкласса оставалась нулевой, и поэтому любые методы делегата не будут вызываться в классе Вы ожидаете, что это будет вызвано. В этом случае то, что вы сделали, является практически единственным способом сделать это; если вам необходимо расширить данный протокол, сделайте так, чтобы класс реализовал это, а затем просто установите класс в качестве делегата UIPickerView.

Редактировать: кстати, потрясающий аватар:)

0 голосов
/ 12 марта 2010

Я пытался сделать нечто подобное - я предполагаю, что вы хотите сгруппировать дополнительные методы, которые вы добавляете в UIImagePickerControllerDelegate, в один файл? Я запускал UIImagePicker из двух мест и хотел, чтобы он вел себя одинаково, не дублируя код.

Что я сделал, так это добавил категорию в UIViewController, например так (ниже). Я довольно новичок в Objective-C (много лет использую C ++), так что это, вероятно, нарушает дух того, кто вы есть " я должен был «делать что-то» (расширение протокола имеет больше смысла), но мой подход достиг того, чего я хотел, поэтому я решил, что я это выброшу.

UIViewController + imagePickerDelegate.h:

 @interface UIViewController (ImagePickerDelegate) <UINavigationControllerDelegate, UIImagePickerControllerDelegate>

    -(void)configurePicker:(UIImagePickerController*)picker;
    ...

@end

UIViewController + imagePickerDelegate.m:

   #import "UIViewController+imagePickerDelegate.h"

    @implementation UIViewController (ImagePickerDelegate) 

    -(void)configurePicker:(UIImagePickerController*)picker
    {
        picker.delegate = self;
        picker.allowsEditing = YES;
    }

    ....

@end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...