установка свойства базового класса протокола для метода с использованием селектора или блока

Я создаю интерфейс / протокол, который будет использоваться для представлений сетки iOS. Я пытаюсь инкапсулировать как можно больше информации внутри класса, оставляя очень мало информации пользователю класса и его подклассов. Я застрял в том, каким должен быть метод обратного вызова или делегат. В C или C ++ я бы потребовал, чтобы указатель на функцию передавался в качестве параметра для метода, который будет вызываться при событии ретуши. В Objective C (в котором я новичок) меня озадачивают блоки и селекторы. Из того, что я видел, Apple использует селекторы. Таким образом, этот класс должен требовать, чтобы метод был установлен в качестве селектора для того, что произойдет при обнаружении события касания. Я не хочу расширять подклассы, так как это ограничит возможность повторного использования и заставит выполнять больше кодирования каждый раз, когда используется этот интерфейс. Я включаю ограниченный код того, что я сделал до сих пор, используя селектор, но я открыт для предложений о том, как то же самое можно сделать с блоком вместо этого и почему это было бы лучше. Я не тестировал это, в настоящее время разрабатываю.

@protocol Grid <NSObject>
@required

/*! @brief Initializer for base class */
- (id) init:(UIView *)parent withSelector:(SEL)selector;
/*! @brief Draw the actual view */
- (void) draw:(CGRect) rect;
/*! @brief Reload the data */
- (void) reload;
@end

Название вводит в заблуждение, и с тех пор, как я разместил этот вопрос, я получил лучшее представление о том, как все работает в Objective-C. Речь идет об абстрагировании базовых классов, наследовании и полиморфизме, а не о настройке селекторов как свойств или делегатов.


person Ælex    schedule 17.08.2012    source источник


Ответы (1)


вам следует потребовать, чтобы класс (предположительно делегат) соответствовал вашему протоколу. Вы можете сделать это вот так.

@interface GridView : UIView {
    id<Grid> delegate;
}

...

@end

и попросите пользователя указать свойство делегата. На данный момент все, что вы знаете о делегате, это то, что он соответствует протоколу Grid, поэтому вы можете быть уверены, что он реализует все необходимые ему методы. Обратите внимание, что у вас никогда не должно быть какого-либо метода инициализации в протоколе, потому что вашему классу (GridView) никогда не нужно выделять свой собственный делегат, что полностью противоречит цели.

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

@interface GridDelegateObject : NSObject <Grid> {
...
}

...

@end

и вам нужно будет предоставить реализацию по крайней мере для требуемых методов в протоколе Grid.

тогда вы должны установить делегата экземпляра GridView на экземпляр GridDelegateObject.

[gridViewInstance setDelegate:gridDelegateObjectInstance];

тогда вы можете вызвать все методы, которые gridDelegateObject реализованы из вашего Grid протокола из gridViewInstance, вот так.

-(void)someMethod {
    [delegate reload];
}

или что-то вроде того. Это вызовет функцию перезагрузки gridDelegateObjectInstance.

person John Corbett    schedule 17.08.2012
comment
Большое спасибо за подробное и исчерпывающее объяснение. Я понимаю, что именно так NextStep строит свои классы, которые мы сейчас используем. Я немного смущен тем, почему мне нужны три класса (судя по вашему примеру) для этого, вместо того, чтобы просто принимать протокол в подклассе напрямую, что требует, чтобы я реализовал методы протокола напрямую (и по-разному) на каждом конкретном экземпляре. подкласс основы. Есть ли у делегации какие-то преимущества? Простите за вопрос, я пришел с C ++, и это кажется мне немного странным, и я все еще думаю в терминах абстрактных базовых классов. - person Ælex; 17.08.2012
comment
Если вы хотите сделать это в подклассе, процесс будет во многом таким же. Просто дайте подклассу принять протокол, реализовать методы протокола и установить для делегата значение self. Таким образом он вызовет все методы делегата в подклассе. Красоты полиморфизма :) - person John Corbett; 17.08.2012