Главная » iPhone, Objective-C, Программирование для iOS и MacOS » Протоколы Objective-C

0

Пришло время обсудить одну, отчасти абстрактную концепцию. Однажды кто-то сказал: «То, что ты есть, и то, что ты делаешь – не одно и то же». Это утверждение справедливо и для объектов: класс объекта не всегда совпадает с его ролью в работающей системе. Например, объект может быть экземпляром NSМutаblеАrrау, тогда как в приложении он может обеспечивать управление очередью заданий печати.

Действительно хорошо написанный класс имеет более общую природу, которая

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

Мы уже говорили о том, как определить класс. Возможно ли определить роль? В определенной степени для определения роли можно использовать конструкцию

@protocol.

Рис. 25.1. Источник данных UIТаblеViеw

Например, в приложениях iOS данные часто отображаются в экземпляре класса UIТаblеViеw. Однако объект UIТаblеViеw не содержит данные, которые в нем отображаются; он должен получить данные из другого источника. Ему необходимо сообщить: «Вот объект, который будет выполнять функции твоего источника данных».

Как разработчик, создавший класс UIТаblеViеw, определил роль источника

данных UIТаblеViеw? Он создал протокол – список объявлений методов. Одни методы являются обязательными, другие относятся к дополнительным. Если ваш объект собирается выполнять функции некоторой роли, он должен реализовать обязательные методы и по желанию реализует дополнительные.

Протокол        источника        данных        для        UIТаblеViеw    называется

UIТаblеViеwDataSource и выглядит следующим образом (с моими комментариями):

// Протоколы, как и классы, могут наследовать от других протоколов.

// Этот протокол наследует от протокола NSObject

@protocol UITableViewDataSource <NSObject>

// следующие методы обязательно должны быть реализованы каждым

// источником данных табличного представления

@required

// табличное представление делится на секции,

// каждая секция может состоять из нескольких строк

-­‐   (NSInteger)tableView:(UITableView  *)tv  numberOfRowsInSection: (NSInteger)section;

// индексный путь состоит из двух целых чисел (секция и строка)

-­‐   (UITableViewCell  *)tableView:(UITableView  *)tv cellForRowAtIndexPath:(NSIndexPath     *)ip;

// а эти методы могут быть (а могут и не быть) реализованы

// источником данных табличного представления

@optional

// если источник данных не реализует этот метод,

// табличное представление состоит только из одной секции

-­‐      (NSInteger)numberOfSectionsInTableView:(UITableView     *)tv;

// Строки могут удаляться и перемещаться

-­‐   (BOOL)tableView:(UITableView  *)tv  canEditRowAtIndexPath:(NSIndexPath  *)ip;

-­‐   (BOOL)tableView:(UITableView  *)tv  canMoveRowAtIndexPath:(NSIndexPath  *)ip;

-­‐  (void)tableView:(UITableView  *)tv commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath    *)ip;

-­‐  (void)tableView:(UITableView  *)tv moveRowAtIndexPath:(NSIndexPath     *)sourceIndexPath

toIndexPath:(NSIndexPath *)destinationIndexPath;

// Для экономии места я опускаю объявления

// нескольких дополнительных методов.

@end

Протоколы, как и классы, тоже имеют свои справочные страницы в документации разработчика Apple, с поддержкой поиска и вывода списка методов протокола.

Когда вы создаете класс, который должен использоваться в качестве источника данных UITableView, вы должны явно указать в заголовочном файле: «Этот класс поддерживает протокол UITableViewDаtаSourсе». Это выглядит примерно так:

@interface TerrificViewController : UIViewController <UITableViewDataSource>

@end

Иначе   говоря,   «TerrificViewController –   субкласс   UIViewController,

который поддерживает протокол UIТаblеViеwDаtаSоurсе».

Если класс поддерживает несколько протоколов, они перечисляются в угловых скобках:

@interface TerrificViewController : UIViewController

<UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate>

Файл TerrificController.m должен содержать реализации обязательных методов в каждом протоколе. Если вы забудете реализовать один из обязательных методов, компилятор выдаст предупреждение.

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

И последнее замечание: в программе Callbacks из главы 24 экземпляр Logger становится делегатом объекта NSURLConnection. Однако в файле Logger.h не указано, что Logger поддерживает соответствующий протокол.

На момент написания книги формального протокола для делегатов NSURLConnection еще не существует. Я не удивлюсь, если это произойдет. (А если при построении программы Callbacks вы получили предупреждение вида «Данный объект не поддерживает протокол NSURLConnectionDelegate», значит, уже произошло.)

Источник: Аарон Хилегас, «Objective-C. Программирование для iOS и MacOS», 2012 г.

По теме:

  • Комментарии