Я создал библиотеку, которая может загружать данные JSON, которые затем помещаются в NSDictionary. Я обернуваю этот класс простым движком Twitter, который позволяет мне вытащить временные рамки моих друзей, опубликовать обновление и опубликовать обновление с моим местоположением GPS. Из моего ограниченного опыта с Objective-C способ подключения ко всему связан с делегацией. Я устанавливаю свойство делегата, которое возвращает асинхронный результат либо селектору, либо методу. Я даже могу создать необязательный или требуемый интерфейс для делегата, который позволит Xcode немного помочь мне в реализации делегирования. Чтобы узнать об использовании делегатов в Objective-C, я создал этот простой проект.Как мне решить проблему множественных обратных вызовов для одного и того же делегата в Objective-C?
http://www.smallsharptools.com/downloads/ObjC/Delegates.zip
Он определяет класс Worker, который позволяет инициализировать класс с делегатом. Когда работа выполняется с помощью метода doWork, он ищет сигнатуру метода в делегате для отправки сообщения обратно. Он использует следующий код.
if([[self delegate] respondsToSelector:@selector(workFinished:)]) {
NSString *msg = @"That's it? Easy!";
[[self delegate] workFinished:msg];
}
Он ищет работуFinished: метод для передачи сообщения. Я объявила эту сигнатуру метода как дополнительный интерфейс со следующим кодом в заголовке Worker.h.
@protocol WorkerNotifications
@optional
- (void) workFinished: (NSString *) msg;
@end
Вы можете увидеть остальную часть проекта из загрузки для всех деталей. Но эти 2 фрагмента кода показывают, как работает этот шаблон делегирования. Но с классом Twitter мне нужно знать контекст метода, который запустил асинхронное действие, которое приводит к обратному вызову методу делегата. Если я вызову метод sendUpdate более одного раза из вызывающего класса, как я должен знать контекст обратного вызова?
Обычно с языком, как JavaScript, Java или C#, я бы создал встроенное закрытие или анонимный класс, который имел бы доступ к исходному контексту, но в настоящее время это не возможно с Objective-C на iPhone. Я обнаружил, что этот вопрос уже задан и ответил на StackOverflow.
Anonymous delegate implementation in Objective-C?
Так что я сделал это пропустить дополнительный интерфейс и вместо этого перешла в селекторе, который класс Twitter будет вызывать, когда асинхронное действие завершено. Вызов для начала этого действия выглядит следующим образом:
CMTwitterEngine *engine = [[CMTwitterEngine alloc] initWithDelegate:self];
[engine setSendUpdateFinished:@selector(sendUpdateFinished:)];
[engine setSendUpdateFailed:@selector(sendUpdateFailed:)];
[engine setParsingSendUpdateFailed:@selector(parsingSendUpdateFailed:)];
[engine setUsername:TWITTER_USERNAME pass:TWITTER_PASSWORD];
[engine sendUpdate:statusUpdateText.text];
Этот код сначала инициализирует ссылку на двигатель как self, как делегат. Чтобы присоединить обратные вызовы, я отправляю в селекторах, которые я изначально использовал на сигнатуре метода sendUpdate, но вызовы метода довольно длинные. Я решил просто установить свойства селекторов. Все это работает, но я не уверен, что мне нравится, как это работает, поскольку оно лишь частично решает мою проблему.
Для завершения этого примера я завершаю асинхронную работу и в конечном итоге вызываю метод внутри, который ищет данный селектор и вызывает его, если он определен.
- (void)sendUpdateFinished:(NSDictionary *)dictionary {
if (self.sendUpdateFinished != nil) {
[self.delegate performSelector:self.sendUpdateFinished withObject:dictionary];
}
}
Я могу передать в сообщение о статусе сообщение для обновления в Twitter, но у меня все еще нет контекста исходящего вызова. Что делать, если я хочу вызвать sendUpdate более одного раза, и первый асинхронный вызов все еще запущен? А что, если второй вызов заканчивается первым? Они оба будут выступать в роли делегата, поэтому мне придется либо отследить контекст каким-то образом, либо передать их другому селектору, чтобы отличить их, что также не удовлетворяет моим потребностям. Что произойдет, если у меня есть 3 или 4 или 5 асинхронных вызова? Мне нужно знать, какие из них были отправлены успешно и когда они завершены.
Кажется, единственный способ, которым я могу это сделать, - создать класс, который содержит все свойства, необходимые для контекста, включить этот класс в качестве делегата для вызова метода асинхронного Twitter, а затем сообщить назад к родительскому классу, который, скорее всего, UIViewController. Я бы взял этот подход, но я не читал об этом подходе или не видел какой-либо пример кода, который делает это.
Что вы хотите сделать? Как бы вы справились с многочисленными асинхронными вызовами, которые могли закончиться в другом порядке, чем выходить, а затем обрабатывать их с контекстом после завершения?
Итак, любой контекст может быть помещен в userInfo NSDictionary? Похоже, что уведомления могут использоваться более чем в одном экземпляре класса, а также пока они оба настроены таким образом. Этот список ссылок от Apple должен помочь мне начать работу. http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Notifications/Introduction/introNotifications.html Спасибо Терри! – Brennan
Пока вы можете сохранить его в качестве значения в словаре, вы можете передавать вещи по мере необходимости. Абсолютно уведомления могут быть отправлены и получены более чем одним классом. В целом они способствуют развязыванию, когда вы хотите, чтобы классы A, B, C и D выполняли некоторые действия, когда происходит какое-то событие, но вы не хотите, чтобы ваш код обработки событий обязательно должен был знать о классах A, B, C , или D. –
Один совет - убедитесь, что вы удалили() своих наблюдателей, объекты, которые вы регистрируете для получения уведомлений, из NSNotificationCenter, когда они больше не нужны. Как правило, если объект зарегистрирован как наблюдатель в методе init, тогда хорошее место для их удаления находится в их реализации dealloc(). –