151

この質問が他の多くの質問のだまされているように見えることはわかっていますが、ここでは単純なケースが十分に説明されているとは思いません. Android と BlackBerry のバックグラウンドから来て、HTTPUrlConnection利用可能な接続がない場合、リクエストをすぐに失敗させます。NSURLConnectionこれは完全に正常な動作のように思えますが、iOS がそれをエミュレートしていないことに驚きました。

ReachabilityApple (およびそれを拡張した他の企業) が、ネットワーク状態の判別を支援するクラスを提供していることを理解しています。私は最初にこれを見てうれしく思いbool isNetworkAvailable()、. もっと良い方法があるはずです。

私のアプリは、接続がないことを含め、接続の失敗を既に適切に処理しています。ユーザーに失敗が通知され、アプリは次に進みます。

したがって、私の要件は単純です。実際にリクエストを送信する必要があるかどうかを判断するために、すべての HTTP リクエストの前に呼び出すことができる単一の同期関数。理想的には、セットアップを必要とせず、ブール値を返すだけです。

これはiOSでは本当に不可能ですか?

4

16 に答える 16

253

もう少し調査を行い、より最新のソリューションで回答を更新しています。あなたがすでにそれを見たかどうかはわかりませんが、Apple が提供する素敵なサンプル コードがあります。

サンプルコードのダウンロードはこちら

Reachability.h ファイルと Reachability.m ファイルをプロジェクトに含めます。ReachabilityAppDelegate.m を見て、ホストの到達可能性、WiFi による到達可能性、WWAN などによる到達可能性を判断する方法の例を確認してください。ネットワークの到達可能性を非常に簡単に確認するには、次のようにします。

Reachability *networkReachability = [Reachability reachabilityForInternetConnection];   
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];    
if (networkStatus == NotReachable) {        
    NSLog(@"There IS NO internet connection");        
} else {        
     NSLog(@"There IS internet connection");        
}

@BenjaminPiette's: SystemConfiguration.framework をプロジェクトに追加することを忘れないでください。

于 2012-01-11T02:06:25.173 に答える
40

返信が遅くなり申し訳ありませんが、この回答が将来誰かに役立つことを願っています。

以下は、クラスを追加せずにインターネット接続をチェックできる小さなネイティブ C コードのスニペットです。

次のヘッダーを追加します。

#include<unistd.h>
#include<netdb.h>

コード:

-(BOOL)isNetworkAvailable
{
    char *hostname;
    struct hostent *hostinfo;
    hostname = "google.com";
    hostinfo = gethostbyname (hostname);
    if (hostinfo == NULL){
        NSLog(@"-> no connection!\n");
        return NO;
    }
    else{
        NSLog(@"-> connection established!\n");
        return YES;
    }
}

スイフト3

func isConnectedToInternet() -> Bool {
    let hostname = "google.com"
    //let hostinfo = gethostbyname(hostname)
    let hostinfo = gethostbyname2(hostname, AF_INET6)//AF_INET6
    if hostinfo != nil {
        return true // internet available
      }
     return false // no internet
    }
于 2013-02-14T07:58:34.473 に答える
11

実装を完了するときにそれを見ると、それは可能であり、非常に単純です。これも非常に単純です。必要な項目は、インターネットの到達可能性とホストの到達可能性という 2 つのブール変数だけであるためです (多くの場合、これらの 2 つ以上が必要です)。 )。接続ステータスを判断できるヘルパー クラスをアセンブルすると、これらの手順を知るために必要な実装についてはまったく気にしなくなります。

例:

#import <Foundation/Foundation.h>

@class Reachability;

@interface ConnectionManager : NSObject {
    Reachability *internetReachable;
    Reachability *hostReachable;
}

@property BOOL internetActive;
@property BOOL hostActive;

- (void) checkNetworkStatus:(NSNotification *)notice;

@end

そして .m ファイル:

#import "ConnectionManager.h"
#import "Reachability.h"

@implementation ConnectionManager
@synthesize internetActive, hostActive;

-(id)init {
    self = [super init];
    if(self) {

    }
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];

    internetReachable = [[Reachability reachabilityForInternetConnection] retain];
    [internetReachable startNotifier];

    hostReachable = [[Reachability reachabilityWithHostName:@"www.apple.com"] retain];
    [hostReachable startNotifier];

    return self;
}

- (void) checkNetworkStatus:(NSNotification *)notice {
    NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
    switch (internetStatus)

    {
        case NotReachable:
        {
            NSLog(@"The internet is down.");
            self.internetActive = NO;

            break;

        }
        case ReachableViaWiFi:
        {
            NSLog(@"The internet is working via WIFI.");
            self.internetActive = YES;

            break;

        }
        case ReachableViaWWAN:
        {
            NSLog(@"The internet is working via WWAN.");
            self.internetActive = YES;

            break;

        }
    }

    NetworkStatus hostStatus = [hostReachable currentReachabilityStatus];
    switch (hostStatus)

    {
        case NotReachable:
        {
            NSLog(@"A gateway to the host server is down.");
            self.hostActive = NO;

            break;

        }
        case ReachableViaWiFi:
        {
            NSLog(@"A gateway to the host server is working via WIFI.");
            self.hostActive = YES;

            break;

        }
        case ReachableViaWWAN:
        {
            NSLog(@"A gateway to the host server is working via WWAN.");
            self.hostActive = YES;

            break;

        }
    }

}

// If lower than SDK 5 : Otherwise, remove the observer as pleased.

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}

@end
于 2012-01-11T00:21:25.750 に答える
6

誰か以前に単純で再利用可能な方法でこれを解決しました。DDGReachability.

編集:またはtonymillion/Reachability

于 2012-01-11T02:09:53.140 に答える
4

私は受け入れられた答えの迅速なバージョンをここに書いています。

必要なファイルはSampleCodeからダウンロードできます。

プロジェクトに追加Reachability.hしてファイルし、Reachability.m

Bridging-Header.hプロジェクトにファイルが存在しない場合は、ファイルを作成する必要があります。

ファイル内に次のBridging-Header.h行を追加します。

#import "Reachability.h"

インターネット接続を確認するために

static func isInternetAvailable() -> Bool {
    let networkReachability : Reachability = Reachability.reachabilityForInternetConnection()
    let networkStatus : NetworkStatus = networkReachability.currentReachabilityStatus()

    if networkStatus == NotReachable {
        print("No Internet")
        return false
    } else {
        print("Internet Available")
        return true
    }

}
于 2015-12-14T06:50:44.547 に答える
4

私はコードを抽出し、1 つのメソッドにまとめました。他の人に役立つことを願っています。

#import <SystemConfiguration/SystemConfiguration.h>

#import <netinet/in.h>
#import <netinet6/in6.h>

...

- (BOOL)isInternetReachable
{    
    struct sockaddr_in zeroAddress;
    bzero(&zeroAddress, sizeof(zeroAddress));
    zeroAddress.sin_len = sizeof(zeroAddress);
    zeroAddress.sin_family = AF_INET;

    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)&zeroAddress);
    SCNetworkReachabilityFlags flags;

    if(reachability == NULL)
        return false;

    if (!(SCNetworkReachabilityGetFlags(reachability, &flags)))
        return false;

    if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
        // if target host is not reachable
        return false;


    BOOL isReachable = false;


    if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
    {
        // if target host is reachable and no connection is required
        //  then we'll assume (for now) that your on Wi-Fi
        isReachable = true;
    }


    if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
         (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
    {
        // ... and the connection is on-demand (or on-traffic) if the
        //     calling application is using the CFSocketStream or higher APIs

        if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
        {
            // ... and no [user] intervention is needed
            isReachable = true;
        }
    }

    if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
    {
        // ... but WWAN connections are OK if the calling application
        //     is using the CFNetwork (CFSocketStream?) APIs.
        isReachable = true;
    }


    return isReachable;


}
于 2012-12-20T10:17:25.443 に答える
0

(iOS) Xcode 8.2 、Swift 3.0 でのインターネット接続の可用性の確認

これは、ネットワークの可用性を確認するための簡単な方法です。私はそれを Swift 2.0 に翻訳することができました。ここに最終的なコードがあります。既存の Apple Reachability クラスやその他のサードパーティ ライブラリは複雑すぎて Swift に変換できないようでした。

これは、3G 接続と WiFi 接続の両方で機能します。

プロジェクト ビルダーに「SystemConfiguration.framework」を追加することを忘れないでください。

//Create new swift class file Reachability in your project.

import SystemConfiguration

public class Reachability {
class func isConnectedToNetwork() -> Bool {
    var zeroAddress = sockaddr_in()
    zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
    zeroAddress.sin_family = sa_family_t(AF_INET)
    let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
        $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
            SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
        }
    }
    var flags = SCNetworkReachabilityFlags()
    if !SCNetworkReachabilityGetFlags(defaultRouteReachability! , &flags) {
        return false
    }
    let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
    let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
    return (isReachable && !needsConnection)
   }
}

// Check network connectivity from anywhere in project by using this code.

if Reachability.isConnectedToNetwork() == true {
     print("Internet connection OK")
} else {
 print("Internet connection FAILED")
}
于 2015-12-17T11:46:15.247 に答える
0

アラモファイア

すでにすべての 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
  }
}

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

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

于 2018-04-02T17:07:39.123 に答える
0

編集:これはネットワーク URL では機能しません (コメントを参照)

iOS 5 では、新しい NSURL インスタンス メソッドがあります。

- (BOOL)checkResourceIsReachableAndReturnError:(NSError **)error

関心のある Web サイトまたは apple.com をポイントします。お使いのデバイスでインターネットが機能しているかどうかを確認するための新しいワンライン コールだと思います。

于 2012-01-28T15:54:08.420 に答える
0

tonymillion にインスパイアされた Swift で書き換えられた Apple の Reachability の置き換え: https://github.com/ashleymills/Reachability.swift

  1. Reachability.swiftファイルをプロジェクトにドロップします。または、 CocoaPodsまたはCarthageを使用します。プロジェクトの README のインストールセクションを参照してください。

  2. ネットワーク接続に関する通知を取得します。

    //declare this property where it won't go out of scope relative to your listener
    let reachability = Reachability()!
    
    reachability.whenReachable = { reachability in
        if reachability.isReachableViaWiFi {
            print("Reachable via WiFi")
        } else {
            print("Reachable via Cellular")
        }
    }
    
    reachability.whenUnreachable = { _ in
        print("Not reachable")
    }
    
    do {
        try reachability.startNotifier()
    } catch {
        print("Unable to start notifier")
    }
    

    および通知を停止するため

    reachability.stopNotifier()
    
于 2017-10-09T13:27:26.093 に答える