Архитектура приложения iOS с NSOperations - PullRequest
10 голосов
/ 04 октября 2010

Два месяца назад я начал писать новое приложение для iPhone, и по этой причине я создал общий веб-сервис RESTFul, который позволяет мне иметь множество таких необходимых функций, как аутентификация пользователя, профили пользователей, система дружбы, обработка мультимедиа , система обмена сообщениями и так далее. На мой взгляд, есть несколько вариантов использования этого веб-сервиса для будущих приложений iPhone.

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

Учитывая мое приложение, существуют сценарии, когда выполняется много параллельных задач (наихудший случай), например пользователь в настоящее время меняет свое изображение профиля, в то время как приложение отправляет местоположение пользователей на сервер (в фоновом режиме), и поступает новое push-уведомление.

Поэтому решили инкапсулировать каждую логическую операцию (например, SendUserLocation или GetCurrentFriendList) в NSOperation и добавить их в serviceQueue (NSOperationQueue).

Каждая операция может порождать подзадачи, когда операция успешно получила результат от веб-службы и должна обработать его сейчас.

alt text

Типичный метод ServiceManager выглядит как

- (void)activateFriendsSync:(id)observer onSuccess:(SEL)selector {
    ELOSyncFriends *opSyncFriends  = [[ELOSyncFriends alloc] initWithSM:self];
    [self ELServiceLogger:opSyncFriends];
    [serviceQueue addOperation:opSyncFriends];
    if(observer) {
        [self registerObserver:observer selector:selector name:opSyncFriends.notificationName]; 
    }
}

Каждая операция, запрос (к серверу) и подзадача используют GUID в качестве источника уведомлений, чтобы уведомить родительский объект о завершении обработки. Если все в операции выполнено, он отправляет уведомление обратно в пользовательский интерфейс.

Тем не менее, код для добавления и удаления подзадач выглядит следующим образом

- (void)removeSubTask:(NSNotification*)notification {
    ELRequest *request = (ELRequest*)[notification object];
    [subTasks removeObjectIdenticalTo:request.notificationName];
    if([subTasks count] == 0) {
         // all SubTaks done, send notification to parent
        [serviceManager.notificationCenter postNotificationName:self.notificationName object:request];
    }
}

- (NSString*)addSubTask {
    NSString* newName = [self GetUUID];
    [subTasks addObject:[newName retain]];
    [serviceManager.notificationCenter addObserver:self selector:@selector(removeSubTask:) name:newName object:nil];
    return newName;
} 

- (NSString *)GetUUID {
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    CFStringRef string = CFUUIDCreateString(NULL, theUUID);
    CFRelease(theUUID);
    return [(NSString *)string autorelease];
}

Теперь все, что мне нужно сделать, это вызвать serviceManager в моем графическом интерфейсе, чтобы запустить определенную операцию, такую ​​как

[self.core.serviceManager activateFriendsSync:nil onSuccess:nil];

Если я хочу зарегистрировать наблюдателя, я просто передаю объект наблюдателя и селектор, подобный этому

[self.core.serviceManager activateFriendsSync:self onSuccess:@selector(myMethod:)];

Последний, но не менее важный мой вопрос (ы) : «Архитектура» работает очень хорошо и стабильно, но стоит ли это делать? Это создает слишком много накладных расходов? Это вообще имеет смысл? Как вы лично осуществляете параллельные операции?

Лучший Хенрик

P.S. Не стесняйтесь редактировать мой вопрос, задавать вопросы (в качестве комментария), называть меня именами для этого мышления.

Мне действительно было трудно объяснить это, в основном потому, что я не являюсь носителем английского языка. И не поймите меня неправильно. Я не писал эту публикацию, чтобы хвастаться в любом виде. Все, что я хочу сделать, это научиться (и, возможно, написать более продвинутый вопрос по iphone / target c)

Ответы [ 3 ]

4 голосов
/ 15 февраля 2011

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

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

еще одним важным соображением является определение потоков на ранних этапах. разрешить клиентам определять, на какой поток они хотят получить ответ. причина этого заключается в том, что часто существует ограничение или логическая запись для обратного вызова, если уведомленный / прослушиватель должен обновить UI (например, вы используете UIKit или AppKit). поэтому создатель может сказать операции «вы должны сообщить мне из основного потока» или «я могу обработать ответ из любого потока». это значительно сократит код вашего контроллера / слушателя / наблюдателя и вероятность ошибок.

2 голосов
/ 07 сентября 2012

Для «подопераций»: как насчет помещения их в очередь, когда родительская операция является зависимостью ( ср. -[ NSOperation addDependency: ]) каждой из ее дочерних операций? NSOperationQueue может упорядочить всю вашу кучу операций для вас. Я думаю, с этим просто и естественно работать.

1 голос
/ 04 октября 2010

Вы только что описали очень похожую архитектуру, которую я использую в нескольких своих приложениях :)

У меня есть слой Service Manager, который мгновенно возвращает набор объектов, а затем возвращает обновленный набор послев то время как

NSArray *stuff = [serviceManager getFriendsForUser:@"Bob"];

, а затем, после ответа сервера, получено уведомление NSNotification, содержащее обновленный список (в данном случае друзей Боба).

Помимо этого крошечного измененияваша архитектура такая же!

Достаточно много работы, чтобы все это настроить, но я думаю, что в долгосрочной перспективе это того стоит, поскольку исправлять ошибки / расширять код гораздо проще.

...