Когда я впервые написал код для представления контроллера модального представления в iOS, я наивно полагал, что последним аргументом presentViewController:animated:completion:
метода был обратный вызов, который будет вызван после того, как пользователь завершит взаимодействие с представлением представленного контроллера (то есть, когда контроллер был отклонен ). Я был удивлен, обнаружив, что мой блок завершения вызывается, как только на экране появляется вид контроллера, а не когда он исчезает. Конечно, после более внимательного прочтения документации я понял, что это было предполагаемое поведение:
completion
— Блок для выполнения после окончания презентации.
К сожалению, это не то, что мне было нужно. После тщетных поисков средств для предоставления контроллеру обратного вызова для вызова при увольнении я, наконец, наткнулся на эту информацию в Руководстве по программированию Apple View Controller для iOS :
Если представленный контроллер представления должен возвращать данные в представляющий контроллер представления, используйте шаблон проектирования делегирования для облегчения передачи … При делегировании представленный контроллер представления сохраняет ссылку на объект делегата, который реализует методы из формального протокола . По мере сбора результатов представленный контроллер представления вызывает эти методы для своего делегата. В типичной реализации представляющий контроллер представления делает себя делегатом своего представленного контроллера представления.
Это было все, что должен был сказать документ — никаких примеров кода или других, более конкретных рекомендаций не было предоставлено. К счастью, после некоторых копаний я смог определить пару существующих классов UIKit, которые я мог бы использовать в качестве модели. UIImagePickerController
, который позволяет пользователю выбрать фотографию или видео для использования в приложении, определяет UIImagePickerControllerDelegate
протокол, который используется для уведомления докладчика, когда пользователь либо делает выбор, либо отменяет операцию:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
Точно так же, ABPeoplePickerNavigationController
который позволяет пользователю выбрать контакт из адресной книги, предоставляет ABPeoplePickerNavigationControllerDelegate
протокол:
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
...
ABPeoplePickerNavigationController
вместе со связанным протоколом устарела в iOS 9, но для его замены CNContactPickerViewController
используется аналогичный подход с CNContactPickerDelegate
:
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact
- (void)contactPickerDidCancel:(CNContactPickerViewController *)picker
...
Используя эти классы в качестве руководства, я смог легко определить и реализовать свой собственный пользовательский делегат контроллера, который уведомляет представляющий контроллер о том, что контроллер регистрации пользователя либо успешно зарегистрировал нового пользователя, либо был отменен:
// Forward reference
@protocol RegistrationViewControllerDelegate;
/**
* Registration view controller.
*/
@interface RegistrationViewController : UITableViewController
@property (weak, nonatomic) id<RegistrationViewControllerDelegate> delegate;
@end
/**
* Registration view controller delegate.
*/
@protocol RegistrationViewControllerDelegate
- (void)registrationViewController:(RegistrationViewController *)registrationViewController didRegisterUser:(User *)user;
- (void)registrationViewControllerDidCancel:(RegistrationViewController *)registrationViewController;
@end