2016-08-02 3 views
8

Я искал интернет, чтобы найти лучший способ проверить подключение к Интернету в iOS, которое работает как в сетевой среде IPv4, так и в сети IPv6. Я обнаружил, что есть много возможных ответов, но очень запутано, на что можно подать заявку. Что мне нужно сделать, это следующее:Лучший подход для проверки подключения к Интернету в iOS

// Check for internet connection 

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

Я нашел следующие варианты, которые предлагаются в Интернете.

ВАРИАНТ 1: Использование яблочного достижимости Класс

С достижимости можно проверить подключение к Интернету, как после чего короткая и прямая, и не надо ждать какого-либо ответа.

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

- (void)viewDidLoad { 
    [super viewDidLoad]; 

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

} 

Но здесь проверка Интернет осуществляются на предварительном полет, что противоречит предложению инженера яблочного, как видно на WWDC video. Также, если вы проверите ReadMe.md, было упомянуто, что Reachability полностью поддерживает IPv6. Но если метод достижимостьForInternetConnection проверен в Reachability.m, они использовали sockaddr_in, sockaddr_in6 не использовался, который рекомендуется для сети IPv6. Поэтому я не знаю, будет ли это работать в сети IPv6.

ВАРИАНТ 2: Использование Alamofire для подключения

  • Просто попробуйте подключиться, как в одном из stackoverflow answer. Код также показано ниже: -

    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)") 
         } 
        } 
    } 
    

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

ВАРИАНТ 3: Используйте версию Тони Миллиона Reachability. Но автор предупреждает о том, что приложение отклоняется при использовании этого. Я могу использовать это как код, показанный ниже: -

// 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]; 
} 

Но в этом варианте, на мой вопрос, это правильный подход, чтобы проверить Интернет путем подключения http://google.com. Гарантирует ли это 100% результаты? Что делать, если Google не работает? Если приложение используется в стране, где google.com не разрешен, какой результат?

Итак, у меня была большая дилемма, которую можно выбрать, если эти варианты верны или есть лучший способ проверки интернета, который гарантирует 100% результаты и работает как в сети IPv4, так и в сети IPv6. Может ли кто-нибудь предложить мне, какой вариант лучше, или я должен пойти на другой подход, что лучше для этого.

Ваш ответ будет очень признателен.

+0

Я бы пошел с родной Досягаемостью. Автоматически отключать опцию 3 из-за возможного отклонения. Вариант 2 может быть в порядке, если вы уже используете Alamofire. – tktsubota

+1

На самом деле, я бы просто сделал правильные вызовы REST, и если вы получите сообщение об ошибке для Интернета, то попробуйте метод возврата. Тестирование его случайным доменом не приведет вас никуда. – tktsubota

+0

Да, это рекомендуемый метод. См. «Подключение без предполета» в https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html. –

ответ

5

Я думаю, вы найдете эту ссылку полезным: 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 

    } 
} 

// случай использования

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

Вот несколько других ссылок для исследования:

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

Я также использовал это решение. Но будет ли это работать и для IPv6, так как sockaddr_in обрабатывает только среду IPv4 в соответствии с этим документом [link] https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html – skJosh

+1

I подумайте, что вы хотите сделать, это изучить метод SCNetworkReachabilityCreateWithName, а не SCNetworkReachabilityCreateWithAddress – Asdrubal

+0

@Asdrubal Эта работа для ipv4 и ipv6? без отказа ipv6 app store? – iajmeri43

12

Для 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. Загрузить папку .zip из Github

  2. разархивировать папку прилагается и перетащить файлы в ваш проект.

  3. Создайте файл bridge.h и импортируйте его с помощью #import "Reachability.h".

  4. Перед вызовом API, вы можете проверить подключение к Интернету с помощью следующего кода:

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

Вот и все.

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