1

в моем приложении Я реализую свою интернет-сеть с глобальной диспетчерской очередью и gcd. Я хочу установить индикатор сети, пока есть активность в сети.Как проверить, пуста ли глобальная диспетчерская очередь?

вот мой сетевой блок ->

{ 
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:YES]; 

send sync http request 

[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO]; 


} 

мои вопросы:

  1. Я хочу, чтобы проверить, есть ли блок, который еще не выполнен! перед тем как скрывать индикатор сети. Как я мог это реализовать!

  2. делает вызов setNetworkActivityIndicatorVisible из другого потока, безопасный, потому что я вижу, что NetworkActivityIndicatorVisible является неатомным.

+0

Вопрос № 1 имеет простой ответ, если вы идете на один уровень выше и используете NSOperationQueue. Отправка блока на него действительно не сложнее, чем GCD, и это дает вам гораздо лучший контроль над операциями. –

+0

@PhillipMills спасибо, я проверю документацию – david

+0

@PhillipMills, но как насчет второго вопроса – david

ответ

2

@ Подход DavidBemerguy - хорошее начало, но вы, как правило, хотите его реализовать с помощью dispatch_group_notify, чтобы скрыть индикатор. Тем не менее, ИМО, вам здесь не нужен GCD. Вам просто нужен NetworkIndicatorController.

Создайте объект (контроллер), который прослушивает уведомления, такие как DidStartNetworkActivity и DidStopNetworkActivity. Отправлять уведомления при запуске или остановке. Внутри контроллера держите подсчет, а когда он достигнет 0, скройте индикатор. Что-то вроде этого (полностью тестировался, просто набрав здесь, и я пишу исключительно в Swift в течение последних нескольких дней, так что простите недостающие точки с запятой):

.h:

extern NSString * const DidStartNetworkActivityNotification; 
extern NSString * const DidStopNetworkActivityNotification; 

@interface NetworkIndicatorController 
- (void) start; 
- (void) stop; 
@end 

.m

@interface NetworkIndicatorController() 
@property (nonatomic, readwrite, assign) NSInteger count; 
@end 

@implementation NetworkIndicatorController 

- (void)start { 
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
    [nc addObserver:self name:DidStartNetworkActivityNotification selector:@selector(didStart:) object:nil]; 
    [nc addObserver:self name:DidStopNetworkActivityNotification selector:@selector(didStop:) object:nil]; 
    self.count = 0; 
} 

- (void)stop { 
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
    [nc removeObserver:self name:DidStartNetworkActivityNotification object:nil]; 
    [nc removeObserver:self name:DidStopNetworkActivityNotification object:nil]; 
} 

- (void)didStart:(NSNotification *)note { 
    dispatch_async(dispatch_get_main_queue(), { 
     self.count = self.count + 1; 
     [[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:YES]; 
    }); 
} 

- (void)didStop:(NSNotification *)note { 
    dispatch_async(dispatch_get_main_queue(), { 
     self.count = self.count - 1; 
     if (self.count <= 0) { 
     [[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO]; 
     } 
    }); 
} 

Вы можете получить похожие материалы с dispatch_group, но я думаю, что это проще. Проблема с подходом диспетчерской группы отслеживает, когда вы это делаете, и не хотите вызывать dispatch_notify. Я уверен, что окончательный код не так уж и трудный, но сложнее подумать обо всех возможных условиях гонки.

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

+0

Это правильный путь.Насколько я знаю, для протокола есть (по крайней мере в настоящее время) нет общедоступного API для определения того, является ли произвольная очередь GCD пустой. – ipmcc

+1

Даже если вы могли бы спросить, была ли очередь пустой, это было бы бесполезно, потому что с момента проверки и времени, когда вы что-то сделали с ней, она может быть не пустой. Хуже того, другие очереди могут нацеливаться на эту очередь и могут изменить, в какую очередь они нацелены. И есть вопрос, является ли очередь пустой, если некоторые из очередей, которые ее нацеливают, приостанавливаются, но на них есть блоки. Вы можете решать все эти вопросы с помощью dispatch_groups, но вам нужно решить, на что вы хотите отвечать, что может быть большой работой: D –

+0

Хорошо сказал, Роб. Хорошо сказано. :) – ipmcc

1

Один из возможных подходов - создать группу задач, а затем ждать их завершения. Между началом и концом вы можете обновить индикатор активности. Очевидно, вам понадобится какой-то объект, который сохранит ссылку на группу. Проверьте этот код, основанный на яблочном документации:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // Retain this queue somewhere accessible from the places you want to dispatch 
dispatch_group_t group = dispatch_group_create(); // Retain this group somewhere accessible from the places you want to dispatch 

// Add a task to the group 
dispatch_group_async(group, queue, ^{ 
    // Some asynchronous work 
}); 

// Do some other work while the tasks execute. 
disptach_sync(dispatch_get_main_queue(), ^{ 
    [[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:YES]; 
} 


// When you cannot make any more forward progress, 
// wait on the group to block the current thread. 
dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 

// Release the group when it is no longer needed. 
disptach_sync(dispatch_get_main_queue(), ^{ 
    [[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO]; 
} 

dispatch_release(group); 

Помните, что вы можете иметь одноплодную объект, который вы посылаете ваши блоки и и отслеживающую ваше ожидания.

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