2011-12-25 2 views
2

Я ищу хороший способ выполнения селектора на главном потоке с двумя параметрамиХороший способ выполнить селектор в основном потоке с двумя параметрами?

мне очень нравится с помощью

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait 

метода, только теперь у меня есть два параметра.

Так в основном у меня есть делегат, который мне нужно уведомить, когда изображение загружается:

[delegate imageWasLoaded:(UIImage *)image fromURL:(NSString *)URLString; 

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

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

NSDictionary *imageData = [NSDictionary dictionaryWithObjectsAndKeys:image, @"image",  URLString, @"URLstring", nil]; 
[(NSObject *)delegate performSelectorOnMainThread:@selector(imageWasLoaded:) withObject: imageData waitUntilDone:NO]; 

Но этот подход не кажется мне правильным. Есть ли более элегантный способ сделать это? Возможно, используя NSInvocation? Спасибо заранее.

ответ

6

Поскольку у вас нет доступа к GCD, NSInvocation, вероятно, ваш лучший выбор здесь.

NSMethodSignature *sig = [delegate methodSignatureForSelector:selector]; 
NSInvocation *invoke = [NSInvocation invocationWithMethodSignature:sig]; 
[invoke setTarget:delegate]; // argument 0 
[invoke setSelector:selector]; // argument 1 
[invoke setArgument:&arg1 atIndex:2]; // arguments must be stored in variables 
[invoke setArgument:&arg2 atIndex:3]; 
[invoke retainArguments]; 
    /* since you're sending this object to another thread, you'll need to tell it 
    to retain the arguments you're passing along inside it (unless you pass 
    waitUntilDone:YES) since this thread's autorelease pool will likely reap them 
    before the main thread invokes the block */ 

[invoke performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:NO]; 
+0

Это правильное решение pre-GCD, и если это будет часто использоваться, его можно легко поместить в пользовательский метод 'performSelectorOnMainThread: withObject: withObject:'. –

+0

Спасибо, это то, что я искал! – dariaa

+0

Должен ли я освобождать что-нибудь после использования? (Поскольку аргументы сохранены) – b123400

1

Да, у вас есть правильная идея: вам необходимо инкапсулировать все данные, которые вы хотите передать делегату на основной поток, в один объект, который передается через performSelectorOnMainThread. Вы можете передать его как объект NSDictionary или объект NSArray или какой-либо пользовательский объект Objective C.

1

метод Следуя также может быть использован:

- (id)performSelector:(SEL)aSelector withObject:(id)anObject withObject:(id)anotherObject 

В соответствии с Документами этого ме- вызывает метод приемника на текущем потоке с использованием режима по умолчанию после задержки.

+1

Но проблема в том, что я хочу, чтобы это было отправлено в основном потоке, независимо от того, в какой поток был вызван – dariaa

8

Использование NSDictionary для передачи нескольких параметров - это правильный способ сделать это в этом случае.

Однако более современный метод заключается в использовании GCD и блоков, таким образом вы можете напрямую отправлять сообщения объекту. Кроме того, похоже, что ваш метод делегирования может делать какие-то обновления пользовательского интерфейса; которые вы правильно обрабатываете на основном потоке. С НОД вы можете сделать это легко, и асинхронно, как это:

dispatch_async(dispatch_get_main_queue(), ^{ 
    [delegate imageWasLoaded:yourImage fromURL:yourString; 
}); 

Заменить performSelector:withObject вызов с этим, и вам не придется возиться с изменением ваших сигнатур методов.

Убедитесь, что вы:

#import <dispatch/dispatch.h> 

принести в поддержку НОД.

+0

Спасибо большое, что попадалось на мой взгляд, но мой OS развертывания 3,0, я дон Не хотите писать другой код для iOS 4.0 и 3.0. А как насчет NSInvocation, можно ли здесь использовать? – dariaa

+0

Действительно? 2 ОС за текущим? Я обновил теги, чтобы отразить это. Но если вы начинаете новое приложение, и если у вас нет ** очень хорошей причины писать для iOS3, вам лучше писать для последнего SDK. – Abizern

+0

Ну, к сожалению, это не мой призыв решить :( – dariaa

 Смежные вопросы

  • Нет связанных вопросов^_^