Использование функций netinet на iPhone приводит к тому, что пользовательский интерфейс не обновляется - PullRequest
1 голос
/ 07 декабря 2009

Я включаю заголовки netinet и занимаюсь программированием необработанных сокетов на iPhone, и обнаружил, что при выполнении этих вызовов пользовательский интерфейс не обновляется до тех пор, пока я не закончу - любой ответ, который я получаю и записываю в пользовательский интерфейс, не записывается, пока IBAction, который совершил вызов, не будет завершен. Используя executeSelector с задержкой, я смог обойти это, но мне было интересно, есть ли лучший способ справиться с этим?

Ответы [ 3 ]

3 голосов
/ 07 декабря 2009

Вы можете отсоединить новый поток и запустить сетевой код следующим способом:

 [NSThread detachNewThreadSelector:@selector(doNetworkStuff:) toTarget:self withObject:nil];

 // ...

 - (void) doNetworkStuff:(id)_param {
     NSAutoreleasePool *_pool = [[NSAutoreleasePool alloc] init];
     // ... do netinet stuff here    
     [_pool release];
 }

Работая с сетью в своем собственном потоке, вы оставляете пользовательский интерфейс свободным для выполнения обновлений.

3 голосов
/ 07 декабря 2009

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

CFSocket является достаточно низкоуровневым, поэтому вы, вероятно, можете использовать любую форму сетевого обмена данными, которую вы пытаетесь, но он поможет вам, добавив интеграцию Run Loop. Используя цикл выполнения, вы можете избежать многопоточности вашего кода. Использование цикла выполнения обрабатывает сетевые события как любой другой источник событий для вашего приложения.

См. Руководство по программированию CFNetwork для получения дополнительной информации.

0 голосов
/ 07 декабря 2009

Самый простой способ, который я нашел, - это раскрутить вторую нить. Прочтите Руководство по программированию потоков .

Затем я возвращаюсь к интерфейсу через executeSelectorOnMainThread: withObject: waitUntilDone: . Легко отправить и NSObject, который инкапсулирует данные, полученные из сети.

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

@interface Question {
    NSString *question;
    NSString *answer;
}
@end

@interface QuestionQueryResults {
    NSMutableArray *questions;
}
@end

и у меня есть контроллер представления со следующим открытым методом:

@interface QuestionsController : UIViewController {
}
- (void)setQuestions:(QuestionQueryResults*)questions;
@end

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

Потоковый код будет выглядеть примерно так:

void performQuery(QuestionsController *delegate) {

    QuestionQueryResults *results = [[QuestionQueryResults alloc] init];

    // Process the network data to fill in results

    [delegate performSelectorOnMainThread:@selector(setQuestions:)
              withObject:results
              waitUntilDone:YES]; // Wait so we can `release` the results

    [results release];        
}

Вы можете рассматривать QuestionQueryResults как «ViewModel» в архитектуре MVC. Прекрасно работает и производит минимальные глюки интерфейса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...