Frage

Ich weiß, dass diese Frage ein Betrüger vieler anderer zu sein scheint. Ich bin jedoch nicht der Meinung, dass der einfache Fall hier gut erklärt wird. Aus einem Android- und Blackberry -Hintergrund kommen und Anfragen durchführen HTTPUrlConnection Versagen Sie sofort, wenn keine Verbindung verfügbar ist. Dies scheint ein völlig vernünftiges Verhalten zu sein, und ich war überrascht zu finden NSURLConnection in iOS hat es nicht nachgedacht.

Ich verstehe, dass Apfel (und andere, die es erweitert haben) eine liefern Reachability Klasse, um den Netzwerkstaat zu bestimmen. Ich war froh, das zuerst zu sehen und von so etwas zu erwarten, so etwas wie zu sehen bool isNetworkAvailable(), aber stattdessen fand ich zu meiner Überraschung ein komplexes System, das Benachrichtigungsregistrierungen und Rückrufe und ein paar scheinbar unnötige Details erfordert. Es muss einen besseren Weg geben.

Meine App behandelt bereits anmutig Verbindungsfehler, einschließlich keiner Konnektivität. Der Benutzer wird über den Fehler informiert, und die App geht weiter.

Daher sind meine Anforderungen einfach: Single, synchrone Funktion, die ich vor allen HTTP -Anfragen aufrufen kann, um festzustellen, ob ich die Anfrage tatsächlich senden sollte oder nicht. Idealerweise erfordert es keine Einrichtung und gibt nur einen Booleschen zurück.

Ist das auf iOS wirklich nicht möglich?

War es hilfreich?

Lösung

Ich habe ein bisschen mehr recherchiert und aktualisiere meine Antwort mit einer aktuelleren Lösung. Ich bin mir nicht sicher, ob Sie es sich bereits angesehen haben, aber es gibt einen schönen Beispielcode von Apple.

Laden Sie den Beispielcode herunter hier

Fügen Sie die Dateien der Erreichbarkeit und Erreichbarkeit.m in Ihr Projekt ein. Schauen Sie sich die ReacityAppdelegate.m an, um ein Beispiel zu sehen, wie die Erreichbarkeit des Hosts, die Erreichbarkeit von WLAN, durch WWAN usw. ermittelt werden kann. Wenn Sie eine sehr einfache Überprüfung der Network -Erreichbarkeit überprüfen können, können Sie so etwas tun

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

@Benjaminpiette: Vergessen Sie nicht, Ihrem Projekt SystemConfiguration.Framework hinzuzufügen.

Andere Tipps

Da dieser Thread das Top -Google -Ergebnis für diese Art von Frage ist, dachte ich, ich würde die Lösung bereitstellen, die für mich funktioniert hat. Ich habe schon benutzt AFNetworking, Aber die Suche enthüllte nicht, wie diese Aufgabe mit AFNetworking bis in Mitte meines Projekts erledigt werden kann.

Was Sie wollen, ist dieAfnetworkingReachabilityManager.

// -- Start monitoring network reachability (globally available) -- //
[[AFNetworkReachabilityManager sharedManager] startMonitoring];

[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {

    NSLog(@"Reachability changed: %@", AFStringFromNetworkReachabilityStatus(status));


    switch (status) {
        case AFNetworkReachabilityStatusReachableViaWWAN:
        case AFNetworkReachabilityStatusReachableViaWiFi:
            // -- Reachable -- //
            NSLog(@"Reachable");
            break;
        case AFNetworkReachabilityStatusNotReachable:
        default:
            // -- Not reachable -- //
            NSLog(@"Not Reachable");
            break;
    }

}];

Sie können auch Folgendes verwenden, um die Erreichbarkeit synchron zu testen (sobald die Überwachung begonnen hat):

-(BOOL) isInternetReachable
{
    return [AFNetworkReachabilityManager sharedManager].reachable;
}

Tut mir leid, dass ich zu spät geantwortet habe, aber ich hoffe, diese Antwort kann jemandem in Zukunft helfen.

Im Folgenden finden Sie einen kleinen nativen C -Code -Snippet, mit dem die Internetverbindung ohne zusätzliche Klasse überprüft werden kann.

Fügen Sie die folgenden Header hinzu:

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

Code:

-(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;
    }
}

Swift 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
    }

Ich verwende derzeit diese einfache synchrone Methode, für die keine zusätzlichen Dateien in Ihren Projekten oder Delegierten erforderlich sind.

Importieren:

#import <SystemConfiguration/SCNetworkReachability.h>

Erstellen Sie diese Methode:

+(bool)isNetworkAvailable
{
    SCNetworkReachabilityFlags flags;
    SCNetworkReachabilityRef address;
    address = SCNetworkReachabilityCreateWithName(NULL, "www.apple.com" );
    Boolean success = SCNetworkReachabilityGetFlags(address, &flags);
    CFRelease(address);

    bool canReach = success
                    && !(flags & kSCNetworkReachabilityFlagsConnectionRequired)
                    && (flags & kSCNetworkReachabilityFlagsReachable);

    return canReach;
}

Dann, wenn Sie dies in einen eingefügt haben MyNetworkClass:

if( [MyNetworkClass isNetworkAvailable] )
{
   // do something networky.
}

Wenn Sie im Simulator testen, schalten Sie das WLAN Ihres Mac ein und aus, da der Simulator die Telefoneinstellung ignoriert.

Aktualisieren:

  1. Am Ende habe ich einen Thread/einen asynchronen Rückruf verwendet, um das Blockieren des Hauptfadens zu vermeiden. und regelmäßig testet, damit ich ein zwischengespeichertes Ergebnis verwenden kann - obwohl Sie vermeiden sollten, dass Datenverbindungen unnötig geöffnet werden.

  2. Wie @Thunk beschrieben, gibt es bessere URLs zu verwenden, die Apple selbst verwenden. http://cadinc.com/blog/why-your-apple-ios-7-tevice-wont-connect-the-wifi-network

Es ist möglich und es ist wirklich einfach, wenn Sie es bei der Beendigung der Implementierung ansehen, was wiederum ist - sehr einfach, da die einzigen Elemente, die Sie benötigen ). Sobald Sie Ihre Helferklasse zusammengebaut haben, die den Status der Verbindungen bestimmen kann, ist es Ihnen wirklich egal, die Implementierung für diese Verfahren erforderlich zu sein.

Beispiel:

#import <Foundation/Foundation.h>

@class Reachability;

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

@property BOOL internetActive;
@property BOOL hostActive;

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

@end

Und die .m -Datei:

#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

Jemand hat löste dies auf einfache, wiederverwendbare Weise zuvor. DDGReachability.

Editor tonymillion/Reachability.

Ich habe den Code extrahiert und in eine einzige Methode gebracht, hoffe, er würde anderen helfen.

#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;


}

Ich denke, das könnte helfen.

[[AFNetworkReachabilityManager sharedManager] startMonitoring];

if([AFNetworkReachabilityManager sharedManager].isReachable)
{
    NSLog(@"Network reachable");
}
else
{   
   NSLog(@"Network not reachable");
}

Ich schreibe die schnelle Version der akzeptierten Antwort hier, Wenn jemand es nützlich findet, wird der Code Swift 2 geschrieben.

Sie können die erforderlichen Dateien von herunterladen Beispielcode

Hinzufügen Reachability.h und Reachability.m Datei zu Ihrem Projekt,

Jetzt muss man erstellen Bridging-Header.h Datei, wenn keiner für Ihr Projekt vorhanden ist,

In deinem Bridging-Header.h Datei Fügen Sie diese Zeile hinzu:

#import "Reachability.h"

Um jetzt nach Internetverbindung zu suchen

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
    }

}

Sie können dies auch versuchen, wenn Sie AFNetworking bereits in Ihrem Projekt konfiguriert haben.

-(void)viewDidLoad{  // -- add connectivity notification --//
[[NSNotificationCenter defaultCenter ] addObserver:self selector:@selector(ReachabilityDidChangeNotification:) name:AFNetworkingReachabilityDidChangeNotification object:nil];}
-(void)ReachabilityDidChangeNotification:(NSNotification *)notify
{
// -- NSLog(@"Reachability changed: %@", AFStringFromNetworkReachabilityStatus(status));  -- //
NSDictionary *userInfo =[notif userInfo];
AFNetworkReachabilityStatus status= [[userInfo valueForKey:AFNetworkingReachabilityNotificationStatusItem] intValue];
switch (status)
{
    case AFNetworkReachabilityStatusReachableViaWWAN:
    case AFNetworkReachabilityStatusReachableViaWiFi:
        // -- Reachable -- //
// -- Do your stuff when internet connection is available -- //
        [self getLatestStuff];
        NSLog(@"Reachable");
        break;
    case AFNetworkReachabilityStatusNotReachable:
    default:
        // -- Not reachable -- //
        // -- Do your stuff for internet connection not available -- //
NSLog(@"Not Reachable");
        break;
}
}

Hier finden Sie eine gute Lösung für die Überprüfung der Konnektivität mit Swift, ohne die Erreichbarkeit zu verwenden. Ich habe es dabei gefunden Blog.

Erstellen Sie eine neue Swift -Datei in Ihrem Projekt mit dem Namen Network.swift (zum Beispiel). Fügen Sie diesen Code in diese Datei ein:

import Foundation

public class Network {

    class func isConnectedToNetwork()->Bool{

        var Status:Bool = false
        let url = NSURL(string: "http://google.com/")
        let request = NSMutableURLRequest(URL: url!)
        request.HTTPMethod = "HEAD"
        request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
        request.timeoutInterval = 10.0

        var response: NSURLResponse?

        var data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: nil) as NSData?

        if let httpResponse = response as? NSHTTPURLResponse {
            if httpResponse.statusCode == 200 {
                Status = true
            }
        }

        return Status
    }
}

Sie können dann überall in Ihrem Projekt nach Konnektivität suchen, indem Sie:

if Network.isConnectedToNetwork() == true {
    println("Internet connection OK")
} else {
    println("Internet connection FAILED")
}

Bearbeiten: Dies funktioniert nicht für Netzwerk -URLs (siehe Kommentare)

Ab iOS 5 gibt es eine neue NSURL -Instanzmethode:

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

Zeigen Sie auf die Website, die Sie am Herzen liegen, oder verweisen Sie auf Apple.com. Ich denke, es ist der neue Einstiegsanruf, um festzustellen, ob das Internet auf Ihrem Gerät funktioniert.

Ich war auch mit den verfügbaren Internet -Check -Optionen nicht zufrieden (warum ist das keine native API?!?!)

Mein eigenes Problem war mit 100% Paketverlust - wenn ein Gerät mit dem Router verbunden ist, der Router jedoch nicht mit dem Internet verbunden ist. Die Erreichbarkeit und andere werden ewig hängen. Ich habe eine Utility Singleton-Klasse erstellt, um damit umzugehen, indem ich eine asynchische Auszeit hinzufügte. Es funktioniert gut in meiner App. Ich hoffe es hilft. Hier ist der Link auf GitHub:

https://github.com/fareast555/tfinterneTchecker

Überprüfen Sie die Verfügbarkeit der Internetverbindung in (iOS) Xcode 8.2, Swift 3.0

Dies ist eine einfache Methode zur Überprüfung der Netzwerkverfügbarkeit. Ich habe es geschafft, es in Swift 2.0 und hier den endgültigen Code zu übersetzen. Die vorhandene Apple -Erreichbarkeitsklasse und andere Bibliotheken Dritter schienen zu kompliziert zu sein, um sie in Swift zu übersetzen.

Dies funktioniert sowohl für 3G- als auch für WLAN -Verbindungen.

Vergessen Sie nicht, Ihrem Projektbauer "SystemConfiguration.Framework" hinzuzufügen.

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

Ersatz für die Erreichbarkeit von Apple neu geschrieben in Swift mit Schließungen, inspiriert von Tonymillion: https://github.com/ashleymills/reachability.swift

  1. Lassen Sie die Datei fallen Reachability.swift in Ihr Projekt. Alternativ verwenden Sie Cocoapods oder Karthago - Siehe Installation Abschnitt der Readme des Projekts.

  2. Benachrichtigungen über Netzwerkkonnektivität erhalten:

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

    Und um Benachrichtigungen zu stoppen

    reachability.stopNotifier()
    

Alamofire

Wenn Sie bereits verwenden Alamofire Bei all der erholsamen API können Sie hier daraus werden.

Sie können Ihrer App die folgende Klasse hinzufügen und anrufen MNNetworkUtils.main.isConnected() Um einen Booleschen zu bekommen, ob es verbunden ist oder nicht.

#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
  }
}

Dies ist eine Singleton -Klasse. Jedes Mal, wenn Benutzer das Netzwerk verbinden oder trennen, wird es überschreiben self.reachable zu wahr/falsch richtig, weil wir anfangen, auf die zu hören NetworkReachabilityManager zur Singleton -Initialisierung.

Um die Erreichbarkeit zu überwachen, müssen Sie einen Host bereitstellen. Derzeit verwende ich google.com Wechseln Sie bei Bedarf zu anderen oder anderen Hosts oder einem von Ihnen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top