Najłatwiejszy sposób na wykrycie połączenia internetowego na iOS?

147

Wiem, że to pytanie będzie się wydawało naiwne dla wielu innych, jednak nie sądzę, aby prosty przypadek został tutaj dobrze wyjaśniony. Pochodzące z tła systemu Android i BlackBerry, wysyłanie żądań za pośrednictwem sieci HTTPUrlConnectionnatychmiast kończy się niepowodzeniem, jeśli nie ma dostępnego połączenia. Wydaje się, że jest to całkowicie rozsądne zachowanie i byłem zaskoczony, że NSURLConnectionsystem iOS go nie naśladował.

Rozumiem, że firma Apple (i inne osoby, które ją rozszerzyły) udostępnia Reachabilityklasę pomocną w określaniu stanu sieci. Byłem szczęśliwy, widząc to jako pierwszy, iw pełni oczekiwałem, że zobaczę coś takiego bool isNetworkAvailable(), ale zamiast tego, ku mojemu zdziwieniu, znalazłem złożony system wymagający rejestracji powiadomień i oddzwonień, a także kilka pozornie niepotrzebnych szczegółów. Musi być lepszy sposób.

Moja aplikacja już z wdziękiem obsługuje awarie połączenia, w tym brak łączności. Użytkownik jest powiadamiany o awarii, a aplikacja przechodzi dalej.

Dlatego moje wymagania są proste: pojedyncza, synchroniczna funkcja, którą mogę wywołać przed wszystkimi żądaniami HTTP, aby określić, czy powinienem zawracać sobie głowę wysłaniem żądania, czy nie. W idealnym przypadku nie wymaga konfiguracji i po prostu zwraca wartość logiczną.

Czy to naprawdę nie jest możliwe na iOS?

RealCasually
źródło
Nigdy nie należy wywoływać synchronicznej metody osiągalności sieci przed każdym żądaniem HTTP; wykonywanie tej pracy jest po prostu szalone, chyba że osiągalność asynchronicznie informuje o zmianie warunków sieciowych, a następnie można zrezygnować z wysyłania żądania HTTP. Jest to również cały powód, dla którego istnieją limity czasu (i wtedy powinieneś z wdziękiem obsłużyć ten scenariusz). Zobacz powyższy link, aby uzyskać sposób asynchroniczny
iwasrobbed

Odpowiedzi:

251

Zrobiłem trochę więcej badań i aktualizuję moją odpowiedź za pomocą bardziej aktualnego rozwiązania. Nie jestem pewien, czy już się temu przyjrzałeś, ale jest ładny przykładowy kod dostarczony przez Apple.

Pobierz przykładowy kod tutaj

Dołącz do projektu pliki Reachability.h i Reachability.m. Spójrz na ReachabilityAppDelegate.m, aby zobaczyć przykład, jak określić osiągalność hosta, osiągalność przez Wi-Fi, WWAN itp. Aby bardzo prosto sprawdzić osiągalność sieci, możesz zrobić coś takiego

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: Nie zapomnij dodać SystemConfiguration.framework do swojego projektu.

Semere Taézaz Sium
źródło
46
Nie zapomnij dodać do projektu SystemConfiguration.framework.
Benjamin Piette
1
@chandru To działa. To najłatwiejszy i najskuteczniejszy sposób wykrywania połączenia sieciowego. Proste i łatwe!
S1U
3
Ostrożnie z tym. Uważam, że nie działa niezawodnie po przywróceniu sieci, przynajmniej w symulatorze. Uruchamiam z wyłączonym Wi-Fi i poprawnie zgłasza brak dostępnej sieci; ale potem ponownie włączam Wi-Fi, a SCNetworkReachabilityGetFlags nadal zwraca 0, mimo że rzeczywiste zapytania sieciowe działają dobrze.
Joe Strout
2
Uważam, że moja odpowiedź poniżej ( stackoverflow.com/a/26593728/557362 ) wymaga mniej pracy (bez pobierania innych plików), ale to tylko moja opinia.
GilesDMiddleton
3
Zauważ, że to tylko mówi ci, czy połączenie z określonym hostem jest routowalne . To nie znaczy, że faktycznie możesz się połączyć. Przykład: łączysz Wi-Fi swojego iPhone'a z Wi-Fi aparatu. Wi-Fi jest połączone z bramą domyślną: wszyscy hosty będą zgłaszać osiągalność. Ale tak naprawdę nie jest - kamera jest ślepym zaułkiem.
xaphod
45

Biorąc pod uwagę, że ten wątek jest najlepszym wynikiem w Google dla tego typu pytań, pomyślałem, że dostarczę rozwiązanie, które zadziałało dla mnie. Używałem już AFNetworking , ale wyszukiwanie nie ujawniło, jak wykonać to zadanie za pomocą AFNetworking, aż do połowy mojego projektu.

To, czego chcesz, to AFNetworkingReachabilityManager .

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

}];

Możesz również użyć następujących elementów, aby przetestować osiągalność synchronicznie (po rozpoczęciu monitorowania):

-(BOOL) isInternetReachable
{
    return [AFNetworkReachabilityManager sharedManager].reachable;
}
Sherbertman
źródło
3
Głosowałem za wydaniem tego AFNetworkReachabilityManagerna światło dzienne!
Selvin
Dla tych, dla których nie było to od razu oczywiste: AFNetworking to biblioteka innej firmy.
arlomedia
1
Dostępność sieci to narzędzie diagnostyczne, którego można użyć do zrozumienia, dlaczego żądanie mogło się nie powieść. Nie należy go używać do określania, czy złożyć wniosek, czy nie. - Tak mówi dokumentacja.
Nosov Pavel
AFNetworkReachabilityManager.reachableNIE wykonuje żadnej synchronicznej kontroli. Zwraca wartość logiczną lubreachableViaWWAN i reachableViaWifi.
jdolan
40

Przepraszam, że odpowiadam za późno, ale mam nadzieję, że ta odpowiedź może komuś pomóc w przyszłości.

Poniżej znajduje się mały natywny fragment kodu C, który może sprawdzać łączność z Internetem bez dodatkowej klasy.

Dodaj następujące nagłówki:

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

Kod:

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

Szybki 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
    }
dispatchMain
źródło
3
działa znacznie lepiej niż Apple Reachability. Ale zgodnie z dokumentacją gethostbyname jest przestarzałe i powinieneś użyć getaddrinfo: struct addrinfo * res = NULL; int s = getaddrinfo ("apple.com", NULL, NULL, & res); bool network_ok = (s == 0 && res! = NULL); freeaddrinfo (res);
Tertium
1
Chociaż często używa się google.com do sprawdzania dostępności internetu, warto zauważyć, że jest on blokowany w niektórych krajach. Lepszym wyborem byłyby domeny od firm bardziej „przyjaznych rządowi”, takich jak yahoo.com lub microsoft.com.
laurent
8
@Laurent: Najlepszą opcją jest użycie adresu serwera, z którego będziesz żądać danych. google.com to tylko przykład.
wysyłkaMain
7
Czy to tylko wyszukiwanie DNS? Jeśli tak, czy buforowany wynik DNS mógłby spowodować, że funkcja fałszywie uzna, że ​​sieć jest dostępna?
Stephen Moore
2
@amar Uruchomienie tego w pętli zużywa dane bezprzewodowe, nie chcesz tego robić.
znaczenie ma znaczenie
31

Obecnie używam tej prostej metody synchronicznej, która nie wymaga żadnych dodatkowych plików w twoich projektach lub delegatach.

Import:

#import <SystemConfiguration/SCNetworkReachability.h>

Utwórz tę metodę:

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

Następnie, jeśli umieściłeś to w MyNetworkClass:

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

Jeśli testujesz w symulatorze, włączaj i wyłączaj Wi-Fi komputera Mac, ponieważ wygląda na to, że symulator zignoruje ustawienie telefonu.

Aktualizacja:

  1. W końcu użyłem wątku / asynchronicznego wywołania zwrotnego, aby uniknąć blokowania głównego wątku; i regularnie ponownie testuję, aby móc użyć wyników z pamięci podręcznej - chociaż należy unikać niepotrzebnego utrzymywania otwartych połączeń danych.

  2. Jak opisał @thunk, istnieją lepsze adresy URL do użycia, których używa Apple. http://cadinc.com/blog/why-your-apple-ios-7-device-wont-connect-to-the-wifi-network

GilesDMiddleton
źródło
1
Dzięki i tak samo jak większość innych w tym wątku: nie zapomnij dodać SystemConfiguration.framework do swojego projektu.
eselk
1
Dziwne, w moim projekcie Xcode nie musiałem dodawać pliku SystemConfiguration.framework. Mam SpriteKit, UIKit, StoreKit, Foundation i CoreGraphics, ale nie SystemConfiguration… Czy trwa jakieś niejawne włączenie?
GilesDMiddleton
3
To zadziałało dla mnie, ale kiedy uruchomiłem go po podłączeniu do sieci Wi-Fi, która nie ma połączenia z Internetem, zablokował mój interfejs użytkownika na około 30 sekund. W takiej sytuacji potrzebne jest podejście asynchroniczne.
arlomedia
2
www.apple.comto duża strona internetowa ... lepszym rozwiązaniem będziewww.google.com
Fahim Parkar
2
doskonała odpowiedź! Jedna sugestia: testowy adres URL www.appleiphonecell.comjest podobno dostępny wyłącznie w tym celu i najwyraźniej nie jest blokowany w Chinach.
Thunk
11

Jest to możliwe i jest naprawdę proste, jeśli spojrzysz na to po zakończeniu implementacji, co jest znowu - bardzo proste, ponieważ jedyne elementy, których potrzebujesz, to dwie zmienne logiczne: osiągalność Internetu i osiągalność hosta (często potrzebujesz więcej niż jednej z nich ). Po złożeniu klasy pomocniczej, która może określić stan połączeń, naprawdę nie przejmujesz się implementacją potrzebną do poznania tych procedur.

Przykład:

#import <Foundation/Foundation.h>

@class Reachability;

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

@property BOOL internetActive;
@property BOOL hostActive;

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

@end

Oraz plik .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
Danut Pralea
źródło
4

Wyodrębniłem kod i umieściłem go w jednej metodzie, mam nadzieję, że pomoże to innym.

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


}
Walty Yeung
źródło
[A] Skąd wyodrębniłeś ten kod? Czy możesz zamieścić link do źródła? [B] Bardzo dziękuję za pracę przy wydobywaniu! Dokładnie to, czego potrzebowałem. Miałem sam wykonać to zadanie.
Basil Bourque
Wygląda więc na to, że jest to jedyna odpowiedź, która nie sprawdza żadnego zdalnego serwera (serwerów)?
Jasper
Inni użytkownicy, którzy testują to w systemie MacOS, powinni pamiętać, że kSCNetworkReachabilityFlagsIsWWAN jest przeznaczony dla systemu OS_IPHONE, a nie macOS.
GeoffCoope
4

Piszę tutaj szybką wersję zaakceptowanej odpowiedzi, o ile ktoś uzna ją za przydatną, kod jest napisany szybko 2,

Możesz pobrać wymagane pliki z SampleCode

Dodaj Reachability.hi Reachability.mplik do swojego projektu,

Teraz trzeba będzie utworzyć Bridging-Header.hplik, jeśli żaden nie istnieje dla twojego projektu,

W Bridging-Header.hpliku dodaj tę linię:

#import "Reachability.h"

Teraz, aby sprawdzić połączenie internetowe

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
    }

}
Satyen Udeshi
źródło
3

Myślę, że to mogłoby pomóc ...

[[AFNetworkReachabilityManager sharedManager] startMonitoring];

if([AFNetworkReachabilityManager sharedManager].isReachable)
{
    NSLog(@"Network reachable");
}
else
{   
   NSLog(@"Network not reachable");
}
pooja
źródło
To nie działa, jeśli interfejs sieciowy nie zostanie zmieniony i połączenie internetowe zostanie utracone.
Pratik Somaiya
2

Możesz również spróbować tego, jeśli skonfigurowałeś już AFNetworking w swoim projekcie.

-(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;
}
}
Ravi Raja Jangid
źródło
1

Oto dobre rozwiązanie do sprawdzania łączności za pomocą Swift, bez korzystania z funkcji Reachability. Znalazłem to na tym blogu .

Utwórz nowy plik Swift w swoim projekcie o nazwie Network.swift (na przykład). Wklej ten kod do tego pliku:

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

Następnie możesz sprawdzić łączność w dowolnym miejscu projektu, używając:

if Network.isConnectedToNetwork() == true {
    println("Internet connection OK")
} else {
    println("Internet connection FAILED")
}
wiatraki
źródło
0

EDYTUJ: To nie zadziała dla sieciowych adresów URL (patrz komentarze)

Od wersji iOS 5 istnieje nowa metoda wystąpienia NSURL:

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

Wskaż witrynę, na której Ci zależy, lub wskaż apple.com; Myślę, że jest to nowe połączenie jednowierszowe, aby sprawdzić, czy na Twoim urządzeniu działa internet.

SG1
źródło
Właściwie w moich własnych testach zawsze zwraca to fałsz. Dokumentacja stwierdza, że ​​tak jest w przypadku 4.x, ale w wersji 5+ powinno działać. YMMV
SG1
Wydaje się, że to nie działa w sytuacji, której szukasz. Zobacz stackoverflow.com/questions/9266154/…
Micah Hainline
7
Jest używany w przypadku adresów URL plików, a nie adresów internetowych.
Victor Bogdan
0

Nie byłem również zadowolony z dostępnych opcji sprawdzania w Internecie (Dlaczego to nie jest natywny interfejs API?!?!)

Mój własny problem dotyczył 100% utraty pakietów - gdy urządzenie jest podłączone do routera, ale router nie jest połączony z Internetem. Dostępność i inni będą wisieć na wieki. Utworzyłem użytkową klasę pojedynczą, aby sobie z tym poradzić, dodając limit czasu asynch. Działa dobrze w mojej aplikacji. Mam nadzieję, że to pomoże. Oto link na github:

https://github.com/fareast555/TFInternetChecker

Mike Critchley
źródło
0

Sprawdzanie dostępności połączenia internetowego w (iOS) Xcode 8.2, Swift 3.0

Jest to prosta metoda sprawdzania dostępności sieci. Udało mi się przetłumaczyć to na Swift 2.0 i tutaj ostateczny kod. Istniejąca klasa Apple Reachability i inne biblioteki innych firm wydawały się zbyt skomplikowane, aby można je było przetłumaczyć na Swift.

Działa to zarówno w przypadku połączeń 3G, jak i Wi-Fi.

Nie zapomnij dodać „SystemConfiguration.framework” do narzędzia do tworzenia projektów.

//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")
}
ViJay Avhad
źródło
W Xcode w wersji 7.2 (7C68) ten kod zawiera błędy kompilatora
Daniel
@Daniel, dzięki za wskazanie problemu, to z powodu niebezpiecznych wskaźników, ponieważ Swift 2 / Xcode aktualizuje tam składnie, powinniśmy ich przestrzegać. zaktualizowałem kod dla tego samego. ty;)
ViJay Avhad
Jeśli jesteś podłączony do Wi-Fi, ale nie możesz połączyć się z Internetem (otwórz stronę Google), nadal zwraca prawdę dla osiągalnego. To jest źle.
Arildo Junior
0

Zamiennik Apple Reachability napisany ponownie w Swift z zamknięciami , zainspirowany tonymillion: https://github.com/ashleymills/Reachability.swift

  1. Upuść plik Reachability.swiftdo swojego projektu. Ewentualnie użyj CocoaPods lub Carthage - zobacz sekcję Instalacja w pliku README projektu.

  2. Otrzymuj powiadomienia o łączności sieciowej:

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

    i do zatrzymywania powiadomień

    reachability.stopNotifier()
Pierre F
źródło
0

Alamofire

Jeśli używasz już Alamofire dla wszystkich RESTful Api, oto co możesz z tego skorzystać.

Możesz dodać następującą klasę do swojej aplikacji i zadzwonić, MNNetworkUtils.main.isConnected()aby uzyskać wartość logiczną, czy jest połączona, czy nie.

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

To jest klasa pojedyncza. Za każdym razem, gdy użytkownik łączy lub rozłącza sieć, nadpisuje self.reachablepoprawnie wartość true / false, ponieważ zaczynamy nasłuchiwać NetworkReachabilityManagerinicjalizacji on singleton.

Aby monitorować osiągalność, musisz podać hosta, obecnie używam, w razie potrzeby mogę google.comzmienić na inny lub jeden z twoich.

nuynait
źródło