После разработки для iOS в течение некоторого времени я освоился с языком и пытаюсь улучшить свои навыки в разработке хорошо структурированных приложений. Первоначально я сосредоточился на том, чтобы увидеть что-то функциональное, поэтому я получил гигантские контроллеры представления, которые были ужасно спроектированы. Сейчас я учусь разделять классы моделей и стараюсь сделать свою архитектуру более модульной. Я был бы очень признателен за любые советы по следующей типовой ситуации:
Я занимаюсь разработкой приложения, которое (помимо прочего) извлекает список статей с сервера и отображает их. Тем не менее, пользователь должен пройти проверку подлинности, чтобы иметь возможность получить этот список. Поскольку другие аспекты приложения используют ту же аутентификацию, я хочу, чтобы один класс управлял аутентификацией. Цель состоит в том, что когда любой контроллер запрашивает данные у модели, которая требует аутентификации, если пользователь не аутентифицирован, автоматически будет отображаться приглашение аутентификации.
Я ожидаю создать следующее:
VIEW
- ArticlesView
- AuthenticationView
CONTROLLER
- ArticlesViewController
- AuthenticationViewController
- ArticleManager (синглтон)
- AuthenticationProvider (синглтон)
MODEL
- статья
Когда приложение загружается в первый раз, выполнение достигает метода viewDidLoad ArticlesViewController. В этом методе я получаю общий экземпляр ArticleManager, указываю класс аутентификации, который будет поставщиком аутентификации, и запрашиваю у него список последних статей.
// ArticlesViewController.m
-(void) viewDidLoad {
...
AuthenticationProvider *authProvider = [AuthenticationProvider sharedInstance];
[[ArticleManager sharedInstance] setAuthenticationProvider:authProvider];
[[ArticleManager sharedInstance] fetchNewArticles];
}
Если аутентификация не требуется, ArticleManager успешно извлечет список с сервера и отправит уведомление, сообщающее всем заинтересованным лицам, что статьи были получены. ArticlesViewController будет обрабатывать это уведомление:
// ArticlesViewController.m
- (void) handleNewArticlesNotification:(NSNotification *)note {
[self updateUI];
}
Однако, если требуется аутентификация, пользователю необходимо предоставить экран входа в систему, прежде чем статьи можно будет выбрать и отобразить. Итак, я представляю, что ArticleManager делает что-то вроде этого:
// ArticleManager.m
- (void) fetchNewArticles {
if( [self.authenticationProvider isAuthenticated] ){
// go fetch list from the web
}
else {
[self.authenticationProvider presentAuthenticationRequest];
}
}
Теперь, в этот момент я столкнулся с некоторыми трудностями, уточняя оставшиеся детали. AuthenticationProvider может представлять AuthenticationViewController в качестве модального контроллера представления из rootViewController окна AppDelegate, и AuthenticationProvider будет делегатом AuthenticationViewController. AuthenticationViewController, вероятно, будет глупым для фактических действий, которые он предпринимает, и его делегат (AuthenticationProvider) выполнит работу по аутентификации пользователя. Как только пользователь проходит аутентификацию, AuthenticationProvider отклоняет модальный контроллер представления (AuthenticationViewController).
Но как ArticleManager получает уведомление о том, что запрошенная аутентификация завершена? Он должен был бы иметь возможность обрабатывать как успешные, так и неудачные попытки аутентификации отдельно. Успешная аутентификация в конечном итоге приведет к повторному вызову fetchNewArticles.
Одна мысль состоит в том, чтобы ArticleManager был делегатом AuthenticationProvider. В данном случае это работает, но есть другие менеджеры моделей, которые также могут полагаться на AuthenticationProvider. Предположительно, это будет решено, если AuthenticationProvider не является синглтоном. Это был бы достойный подход к дизайну?
Спасибо, что нашли время помочь мне понять хороший подход к дизайну. Я кодировал это пару раз, но всегда застрял / запутался в конце. Кроме того, если весь подход должен быть перестроен, пожалуйста, не стесняйтесь указывать мне в другом направлении.
Большое спасибо!