web-dev-qa-db-ja.com

iOSでインターネット接続を確認するための最良の方法

IPv4とIPv6の両方のネットワーク環境で機能するiOSでインターネット接続を確認する最良の方法を見つけるために、インターネットを検索してきました。考えられる答えはたくさんありますが、どれを当てはめるか混乱しています。私がする必要があるのは次のとおりです:

   // Check for internet connection

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

インターネットで提案されている次のオプションが見つかりました。

オプション1:Use Apple Reachability class

到達可能性を使用すると、インターネット接続を次のように確認できます。これは短くて直接であり、応答を待つ必要はありません。

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

- (void)viewDidLoad {
    [super viewDidLoad];

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

}

ただし、ここではインターネットチェックは飛行前に行われます。これは、Appleエンジニア WWDCビデオ に見られるエンジニア)の提案に反しています。また、ReadMe.mdをチェックすると、 ReachabilityはIPv6を完全にサポートしていることを述べましたが、メソッドreachabilityForInternetConnectionが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:到達可能性 のTony Millionバージョンを使用します。しかし、作者はこれを使用しているときにアプリが拒否されることを警告しています。これを以下のコードとして使用できます:-

// 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.comが許可されていない国で使用されている場合、結果はどうですか?

したがって、これらのオプションが正しい方法であるか、100%の結果を保証し、IPv4とIPv6の両方のネットワークで機能するインターネットをチェックするより良い方法があるかどうか、私はどのオプションを選択するかという大きなジレンマに陥っています。誰かが私にどのオプションがより良いか、または私が他のアプローチに行くべきか、これを達成するためのより良い方法は何かを提案できますか?.

ご返信いただければ幸いです。

10
skJosh

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)
}
13
emraz

このリンクが役立つと思います: SwiftのIPv6ネットワークでネットワーク接続チェックがクラッシュします

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

7
Asdrubal

アラモファイア

すべてのRESTful APIにすでにAlamofireを使用している場合、そのメリットを次に示します。

次のクラスをアプリに追加し、MNNetworkUtils.main.isConnected()を呼び出して、接続されているかどうかのブール値を取得できます。

#import Alamofire

class MNNetworkUtils {
  static let main = MNNetworkUtils()
  init() {
    manager = NetworkReachabilityManager(Host: "google.com")
    listenForReachability()
  }

  private let manager: NetworkReachabilityManager?
  private var reachable: Bool = false
  private func listenForReachability() {
    self.manager?.listener = { [unowned self] status in
      switch status {
      case .notReachable:
        self.reachable = false
      case .reachable(_), .unknown:
        self.reachable = true
      }
    }
    self.manager?.startListening()
  }

  func isConnected() -> Bool {
    return reachable
  }
}

これはシングルトンクラスです。ユーザーがネットワークを接続または切断するたびに、シングルトン初期化でNetworkReachabilityManagerのリッスンを開始するため、self.reachableをtrue/falseに正しくオーバーライドします。

また、到達可能性を監視するために、ホストを提供する必要があります。現在、私はgoogle.comを使用しています。必要に応じて、他のホストまたはホストに自由に変更してください。

最善の方法として、すでにAlamofireを使用している場合、これが最善の方法になると思います。 google.comの監視は悪い設計だとは思いません。私が間違っている場合は、遠慮なく訂正してください。

1
nuynait
  1. Github から.Zipフォルダーをダウンロードします

  2. 添付されたフォルダを解凍し、ファイルをプロジェクトにドラッグアンドドロップします。

  3. bridge.hファイルを作成し、#import "Reachability.h"を使用してインポートします。

  4. APIを呼び出す前に、次のコードでインターネット接続を確認できます。

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

それでおしまい。

0
Arshad Shaik