2012-07-03 16 views
3

在我的iOS項目,我想顯示一條消息給用戶連接到之前某網絡運營的互聯網,所以我寫了使用蘋果可達類以下檢查:如何以非阻塞方式檢查iOS上的網絡可達性?

Reachability *reach = [Reachability reachabilityWithHostName:@"google.com"]; 
if([reach currentReachabilityStatus] == NotReachable) { 
    // ...prompt user to establish an internet connection 
} else { 
    // ...send an asynchronous request with a timeout 
} 

但是,這有一個非常大的問題 - 當設備處於非常有損耗的網絡中(例如,在OS X Lion的Network Link Conditioner上將上行鏈路數據包丟失設置爲100%時),在確定連接不可用之前,[Reachability reachabilityWithHostName:@"google.com"]會阻塞主線程30秒。下面的代碼,但不阻止:

if([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] == NotReachable) { 
    // ...prompt user to establish an internet connection 
} else { 
    // ...send an asynchronous request with a timeout 
} 

望着可達性的實施表明,這兩種方法都使用SystemConfiguration.framework,但第一種方法使用SCNetworkReachabilityCreateWithName,而第二個使用SCNetworkReachabilityCreateWithAddress。爲什麼第一個方法會阻止,而第二個方法不會呢?第二種方法是檢查連接性的好方法嗎?或者,還有更好的方法?

回答

2

第一個測試它是否可以達到google.com,而第二個只是檢查是否有任何可能的互聯網連接(它認爲存在,即使有包丟失)。

基本上只是把它放在一個線程或後臺隊列中。可靠地知道您是否有良好連接的唯一方法是測試它,並且任何測試將被阻止或異步。你根本無法立即獲得。

+0

能否請你解釋一下你怎麼能明確指出,第二種方法只檢查連接是否是可能的?這是在文檔中說明的地方嗎?如果你能給我一個資料來源,我會將其標記爲正確的答案。 – modocache

+0

任何I/O活動都必須是阻塞的或異步的,以告訴您它是否可以執行某些操作。在你的示例代碼中,你會發現它是同步的,並立即返回。合乎邏輯的結論是沒有涉及I/O。 –

+0

難道這不是'SCNetworkReachabilityCreateWithName'和'SCNetworkReachabilityCreateWithAddress'之間的區別,而是'reachabilityForInternetConnection'檢查套接字地址爲零,從而跳過了檢查遠程主機的時間密集型任務?這裏我只想要一個合理的解釋。 – modocache

4

檢查此功能:

- (BOOL)isNetworkAvailable 
{ 
CFNetDiagnosticRef diag;   
diag = CFNetDiagnosticCreateWithURL (NULL, (__bridge CFURLRef)[NSURL URLWithString:@"www.apple.com"]); 



CFNetDiagnosticStatus status; 
status = CFNetDiagnosticCopyNetworkStatusPassively (diag, NULL);   

CFRelease (diag); 

if (status == kCFNetDiagnosticConnectionUp) 
{ 
    //NSLog (@"Connection is up"); 
    return YES; 
} else { 
    NSLog (@"Connection is down"); 
    return NO; 

} 
} 

這會工作得很好..

+1

真的很好的解決方案,比AFNetworking的測試更好 – lenhhoxung

+0

但是,如果你想檢查一個數據包是否可交付,這也不起作用 – Gihan