1

在我的應用程序我正在實施我的互聯網網絡與全球調度隊列gcd。 我想在網絡活動時設置網絡指示器。如何檢查全局調度隊列是否爲空?

這裏是我的網絡模塊 - >

{ 
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:YES]; 

send sync http request 

[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO]; 


} 

我的問題:

  1. 我想檢查是否有不尚未執行塊!隱藏網絡指標之前。我怎麼能實現這一點!

  2. 確實從另一個線程調用了setNetworkActivityIndi​​catorVisible,因爲我看到NetworkActivityIndi​​catorVisible是非原子的。

+0

問題1有一個簡單的答案,如果你走高一級並使用NSOperationQueue。向GCD提交一個塊實際上並不比GCD困難,它可以更好地控制操作。 – 2014-09-02 13:11:19

+0

@PhillipMills謝謝,我將檢查文檔 – david 2014-09-02 13:19:08

+0

@PhillipMills但第二個問題怎麼樣 – david 2014-09-02 13:19:30

回答

2

@ DavidBemerguy的方法是一個好的開始,但您通常希望通過dispatch_group_notify來實現它以隱藏您的指示器。這就是說,IMO,你不需要GCD。你只需要一個NetworkIndicatorController

創建一個監聽諸如DidStartNetworkActivityDidStopNetworkActivity之類的通知的對象(控制器)。在開始或停止時發佈通知。在控制器內部,保持計數,當它達到0時,隱藏指示器。像這樣的東西(沒有經過測試的,只是這裏打字,我一直在斯威夫特專門寫的最後幾天,所以請原諒所有缺少分號):

.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 2014-09-03 10:45:49

+1

即使你可以詢問一個隊列是否爲空,它也是無用的,因爲在你檢查的時間和你做了些什麼的時候,它可能不再是空的。更糟糕的是,其他隊列可能會將這個隊列作爲目標,並可能改變它們的目標隊列。還有一個問題是,如果某個隊列中的某些隊列被暫停但隊列上有阻塞,那麼隊列是否爲空。你可以用dispatch_groups來解決所有這些問題,但是你必須決定你想要的答案是什麼,這可能是很多工作:D – 2014-09-03 12:45:08

+0

好吧,羅布。說得好。 :) – ipmcc 2014-09-03 13:12:45

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); 

記住,你可以有你的調度塊,並跟蹤你的等待一個單獨的對象。