2016-08-02 10 views
8

Szukałem przez Internet, aby znaleźć najlepszy sposób sprawdzenia połączenia internetowego w iOS, które działa zarówno w środowisku sieciowym IPv4, jak i IPv6. Zauważyłem, że istnieje wiele możliwych odpowiedzi, ale bardzo zdezorientowanych, na które można się zwrócić. Co muszę zrobić, to:Najlepsze podejście do sprawdzania połączenia z Internetem w iOS

// Check for internet connection 

if (internetConnectionIsAvailable) { 
    // make rest calls 
}else 
    // show cached data 
} 

Znalazłem następujące opcje, które są sugerowane w Internecie.

OPCJA 1: Zastosowanie jabłko osiągalności klasa

Z osiągalności mogę sprawdzić łączność z Internetem w następujący sposób, który jest krótki i bezpośredni, i nie trzeba czekać na jakiekolwiek odpowiedzi.

- (BOOL)connected 
    { 
     Reachability *reachability = [Reachability reachabilityForInternetConnection]; 
     NetworkStatus networkStatus = [reachability currentReachabilityStatus]; 
     return !(networkStatus == NotReachable); 
    } 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    if (![self connected]){ 
    // Not connected 
    }else{ 
    // Connected 
    } 

} 

Ale tutaj sprawdzanie www odbywa się przed lotem, który jest przeciwko sugestii przez Apple inżynier jak widać na WWDC video. Również jeśli zaznaczysz ReadMe.md, wspomniano, że zasięg w pełni obsługuje IPv6. Ale jeśli metoda osiągalna jest dla Reachability.m. jest zaznaczona w Reachability.m, to użyli sockaddr_in, sockaddr_in6 nie został użyty, co jest zalecane dla sieci IPv6. Nie wiem więc, czy zadziała w sieci IPv6.

Opcja 2: Wykorzystanie Alamofire połączyć

  • Wystarczy spróbować połączyć się jak w jednym z stackoverflow answer. Kod także przedstawiono poniżej: -

    Alamofire.request(.GET,"http://superrandomdomainnamethatisnotused.com/superrandompath").responseString { 
        (request, response, stringData, error) in 
    
        if let networkError = error { 
         if (networkError.code == -1009) { 
          println("No Internet \(error)") 
         } 
        } 
    } 
    

Ale nie jest to czasochłonne, aby spróbować połączyć się z jakiegoś gospodarza, czekać na odpowiedź i wtedy wiem, czy online/offline.

OPCJA 3: Użyj wersji Tony Milliona Reachability. Autor ostrzega jednak przed odrzuceniem aplikacji podczas korzystania z niej. mogę użyć tego jako kod pokazany poniżej: -

// Checks if we have an internet connection or not 
- (void)testInternetConnection 
{ 
    internetReachableFoo = [Reachability reachabilityWithHostname:@"www.google.com"]; 

    // Internet is reachable 
    internetReachableFoo.reachableBlock = ^(Reachability*reach) 
    { 
     // Update the UI on the main thread 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      NSLog(@"There in internet connection"); 
     }); 
    }; 

    // Internet is not reachable 
    internetReachableFoo.unreachableBlock = ^(Reachability*reach) 
    { 
     // Update the UI on the main thread 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      NSLog(@"Someone broke the internet :("); 
     }); 
    }; 

    [internetReachableFoo startNotifier]; 
} 

Ale w tej opcji, moje pytanie brzmi, czy to jest właściwe podejście do testowania Internetu poprzez podłączenie http://google.com. Czy to gwarantuje 100% wyników? Co jeśli Google nie działa? Jeśli aplikacja jest używana w kraju, w którym domena google.com jest niedozwolona, ​​jaki jest wynik?

Tak więc byłem w wielkim dylemacie, którą opcję wybrać, czy te opcje są właściwe, czy istnieje lepszy sposób sprawdzenia internetu, który gwarantuje 100% wyników i działa zarówno w sieci IPv4, jak i IPv6. Czy ktoś może zasugerować mi, która opcja jest lepsza, czy powinienem wybrać inne podejście, jaki jest lepszy sposób na osiągnięcie tego.

Twoja odpowiedź będzie doceniona.

+0

Chciałbym iść z natywnym zasięgu. Automatycznie wyłącz opcję 3 z powodu możliwego odrzucenia. Opcja 2 może być w porządku, jeśli już używasz Alamofire. – tktsubota

+1

Właściwie to po prostu wykonam odpowiednie wywołania REST, a jeśli pojawi się błąd dla żadnego Internetu, _then_ wywołaj metodę zastępczą. Testowanie go za pomocą losowej domeny nie doprowadzi cię nigdzie. – tktsubota

+0

Tak, to jest zalecana metoda. Zobacz "Łączenie bez inspekcji wstępnej" w https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/Understanding andPreparingfortheIPv6Transition.html. –

Odpowiedz

5

myślę znajdziesz link pomocny: Network connection check crashing on IPv6 networks in Swift

import SystemConfiguration 

class Reachability { 

    class func isConnectedToNetwork() -> Bool { 

     var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0)) 
     zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress)) 
     zeroAddress.sin_family = sa_family_t(AF_INET) 

     let defaultRouteReachability = withUnsafePointer(&zeroAddress) { 
      SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, UnsafePointer($0)) 
     } 

     var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0) 
     if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false { 
      return false 
     } 

     let isReachable = flags == .Reachable 
     let needsConnection = flags == .ConnectionRequired 

     return isReachable && !needsConnection 

    } 
} 

// Użyj przypadek

if Reachability.isConnectedToNetwork() { 
    //do something 
} 

Oto kilka innych linki do badań:

https://developer.apple.com/reference/systemconfiguration/1514904-scnetworkreachabilitycreatewithn

https://developer.apple.com/library/prerelease/content/documentation/Networking/Conceptual/SystemConfigFrameworks/SC_Intro/SC_Intro.html#//apple_ref/doc/uid/TP40001065

+0

Miałem również zastosowanie tego rozwiązania. Ale czy będzie to działało również dla IPv6, ponieważ sockaddr_in obsługuje tylko środowisko IPv4 zgodnie z tym dokumentem [link] https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html – skJosh

+1

I pomyśl, co chcesz zrobić, to poznaj metodę SCNetworkReachabilityCreateWithName zamiast SCNetworkReachabilityCreateWithAddress – Asdrubal

+0

@Asdrubal Czy to działa zarówno dla ipv4 i ipv6? bez odrzucenia sklepu z aplikacjami ipv6? – iajmeri43

12

Dla Swift 3, Xcode 8 ......

func isInternetAvailable() -> Bool { 

    var zeroAddress = sockaddr_in() 
    zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size) 
    zeroAddress.sin_family = sa_family_t(AF_INET) 

    guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, { 
     $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { 
      SCNetworkReachabilityCreateWithAddress(nil, $0) 
     } 
    }) else { 
     return false 
    } 

    var flags: SCNetworkReachabilityFlags = [] 
    if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) { 
     return false 
    } 

    let isReachable = flags.contains(.reachable) 
    let needsConnection = flags.contains(.connectionRequired) 

    return (isReachable && !needsConnection) 
} 
0
  1. Pobierz folder .zip z Github

  2. Rozpakuj do folderu przywiązany i przeciągnąć i upuścić pliki do swojej projekt.

  3. Utwórz plik bridge.h i zaimportuj go, używając #import "Reachability.h".

  4. przed wywołaniem funkcji API, można sprawdzić połączenia internetowego za pomocą następującego kodu:

    if kNetworkController.checkNetworkStatus() { 
        // call your api 
    } 
    

to wszystko.

Powiązane problemy