2015-09-01 9 views
1

Каждый раз, когда я вызываю вызов API на свой сервер для получения данных, я уже знаю, что для выполнения команд изменения интерфейса я должен использовать следующий блок, потому что мой API-вызов выполняется в фоновом режиме:iOS - когда вызывать пользовательский интерфейс Изменение функций в главной теме

dispatch_async(dispatch_get_main_queue(), ^{ 
    //do UI stuff 
}); 

Однако, если у меня есть функция, которая меняет пользовательский интерфейс вне блока вызова API? Например:

-(void)doALotOfUIChanging 
{ 
    //do a lot of UI changing 
} 

В моем блоке вызова API, нужно ли мне позвонить, что UI изменения функции в главном потоке, как так ?:

[apiObject getDataFromObject:my.Object successCallback:^(Array *data) 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [self doALotOfUIChanging]; 
    }); 
} 
errorCallback:^(NSString *error) 
{ 
    NSLog(@"%@", error); 
}]; 

Или я не должен называть его в основной поток, так как функция уже вне блока API вызова, как так ?:

[apiObject getDataFromObject:my.Object successCallback:^(Array *data) 
{ 
    [self doALotOfUIChanging]; 
} 
errorCallback:^(NSString *error) 
{ 
    NSLog(@"%@", error); 
}]; 

у меня также есть функции, которые выполняют перетекает на другие контроллеры просмотра, поэтому я также интересно, если я должен назвать их в основной threa d также. Я делаю очистку кода, и я не хочу постоянно переписывать функцию dispatch_async в ситуациях, которые мне могут не понадобиться, поэтому любая помощь или совет будут очень признательны. Благодарю.

ответ

1

Короткий ответ: Да, вы должны обновить свой интерфейс в основной теме.

Тема и Ваш пользовательский интерфейс

Если ваше приложение имеет графический пользовательский интерфейс, рекомендуются , что вы получаете пользовательские события, связанные и инициировать обновление интерфейса из основного потока приложения. Такой подход помогает избежать проблем синхронизации, связанных с обработкой пользовательских событий и . Некоторые структуры, такие как Cocoa, обычно требуют такого поведения, но даже для тех, которые этого не делают, сохранение этого поведения в основном потоке имеет преимущество в упрощении логики для управления вашим пользовательским интерфейсом.

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

Ссылка:

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/AboutThreads/AboutThreads.html

+0

Спасибо. Включает ли это также настройку наблюдателей для «NSNotificationCenter», если функции, которые будут выполняться позже, изменят интерфейс? – Rafi

+0

Как правило, селектор NSNotification запускается в потоке, на котором они отправляются, если вы не используете « - addObserverForName: object: queue: usingBlock:». – gagarwal

+0

Oooooh ok, это здорово знать. Потому что я добавляю наблюдателей для уведомлений с помощью «useBlock». Использование отправки для запуска в главной очереди будет иметь такое же влияние, что и «useBlock»? – Rafi

0

Прежде всего, вы никогда не должны использовать себя внутри блока. Вы можете использовать __weak yourClassName * weakSelf = self вместо этого.

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

[apiObject getDataFromObject:my.Object successCallback:^(Array *data) 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [weakSelf doALotOfUIChanging]; 
    }); 
} 

Надеюсь, это поможет.:)

+0

Почему я должен использовать «слабое я»? – Rafi

+0

Это делается для того, чтобы не было сохраненного цикла сохранения. Ваш объект (self) имеет явную сильную ссылку на блок. И блок имеет скрытую сильную ссылку на себя. Это цикл, и теперь ни один объект не будет освобожден должным образом. –

+0

Ooooh, но что, если я хотел бы присвоить данные сильному свойству 'NSArray' моего класса? Был бы слабый Self.array = данных или это ничего не сделало бы, так как слабый сам слабый? – Rafi