Ты прав. Встраивание этой функциональности в контроллеры представлений является ненужным и плохой инкапсуляцией.
В парадигме MVC модели часто имеют контекст данных. Контексты данных управляют связью с внутренним хранилищем (в iOS это, как правило, веб-служба или локальный файл) для заполнения и архивирования объектов модели. Для аутентифицированного контекста данных у вас есть свойство для имени пользователя, пароля и состояния аутентификации.
@interface DataContext : NSObject
//Authentication
@property (nonatomic, strong) NSString * username;
@property (nonatomic, strong) NSString * password;
@property (nonatomic, assign) NSInteger authenticationState;
-(void)login;
//Data object methods from authenticated data source (web service, etc)
-(NSArray *)foos;
-(NSArray *)bars;
@end
Аутентифицированное состояние может быть простым логическим значением или целым числом, если вы хотите отслеживать множество состояний (аутентифицировано, неаутентифицировано, неаутентифицировано после попытки аутентификации с сохраненными учетными данными). Теперь вы можете наблюдать за свойством authenticationState
, чтобы позволить вашему уровню контроллера принимать меры при изменении состояния аутентификации.
При запросе данных от вашего веб-сервиса вы меняете состояние аутентификации, когда сервер отклоняет запрос из-за неверных учетных данных.
-(NSArray *)foos
{
NSArray * foos = nil;
//Here you would make a web service request to populate the foos array from your web service.
//Here you would inspect the status code returned to capture authentication errors
//I make my web services return status 403 unauthorized when credentials are invalid
int statusCode = 403;
if (statusCode == 403)
{
self.authenticationState = 0;//Unauthorized
}
return foos;
}
Контроллер — это делегат вашего приложения. В нем хранится экземпляр нашего DataContext. Он отслеживает изменения в этом свойстве authenticated
и отображает представление или повторяет попытку аутентификации, когда это необходимо.
- (void)observeAuthenticatedState:(NSNotification *)notification
{
DataContext * context = [notification object];
if (context.authenticatedState == 0)//You should have constants for state values if using NSIntegers. Assume 0 = unauthenticated.
{
[self.context login];
}
if (context.authenticatedState == -1)//You should have constants for state values if using NSIntegers. Assume -1 = unauthenticated after attempting authentication with stored credentials
{
UIViewController * loginController = nil;//Instantiate or use existing view controller to display username/password to user.
[[[self window] rootViewController] presentViewController:loginController
animated:YES
completion:nil];
}
if (context.authenticatedState == 1)//authenticated.
{
[[[self window] rootViewController] dismissViewControllerAnimated:YES
completion:nil];
}
}
В вашей раскадровке вы можете в основном притворяться, что аутентификация не существует, потому что ваш делегат приложения вставляет пользовательский интерфейс для аутентификации всякий раз, когда контекст данных сообщает, что это необходимо.
person
Fruity Geek
schedule
30.10.2013