Jak sprawdzić aktywne połączenie internetowe na iOS lub macOS?

1324

Chciałbym sprawdzić, czy mam połączenie internetowe w systemie iOS za pomocą bibliotek Cocoa Touch lub w systemie macOS za pomocą bibliotek Cocoa .

Wymyśliłem sposób na zrobienie tego za pomocą NSURL. Sposób, w jaki to zrobiłem, wydaje się nieco niewiarygodny (ponieważ nawet Google może pewnego dnia przestać działać, a poleganie na stronie trzeciej wydaje się złe) i chociaż mogłem sprawdzić, czy nie ma odpowiedzi z innych witryn, jeśli Google nie zareaguje, wydaje się marnotrawstwem i niepotrzebnym kosztem mojej aplikacji.

- (BOOL) connectedToInternet
{
    NSString *URLString = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com"]];
    return ( URLString != NULL ) ? YES : NO;
}

Czy to, co zrobiłem źle, (nie wspominając o tym stringWithContentsOfURLjest przestarzałe w iOS 3.0 i macOS 10.4), a jeśli tak, to jaki jest lepszy sposób na osiągnięcie tego?

Brock Woolf
źródło
11
Raczej return (BOOL)URLString;, a nawet lepiej, return !!URLStringlubreturn URLString != nil
3
Nie wiem, jaki jest twój przypadek użycia, ale jeśli możesz, lepiej wypróbować żądanie i obsłużyć wszelkie błędy, takie jak brak połączenia. Jeśli nie możesz tego zrobić, w tej sprawie jest wiele dobrych rad.
SK9
2
Twoje rozwiązanie jest sprytne i wolę je. Możesz także użyć NSString *URLString = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"https://twitter.com/getibox"] encoding:NSUTF8StringEncoding error:nil];Aby pozbyć się irytującego ostrzeżenia.
Abdelrahman Eid
4
spróbuj użyć klasy Reachability z poniższego linku, to zadziała dla ciebie github.com/tonymillion/Reachability
Dhaval H. Nena
4
Dla tych, którzy niedawno znaleźli tę odpowiedź: stackoverflow.com/a/8813279
afollestad

Odpowiedzi:

1284

Ważne : to sprawdzenie należy zawsze wykonywać asynchronicznie. Większość poniższych odpowiedzi jest zsynchronizowana, więc bądź ostrożny, w przeciwnym razie zawiesisz aplikację.


Szybki

1) Zainstaluj za pośrednictwem CocoaPods lub Carthage: https://github.com/ashleymills/Reachability.swift

2) Test osiągalności poprzez zamknięcia

let reachability = Reachability()!

reachability.whenReachable = { reachability in
    if reachability.connection == .wifi {
        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")
}

Cel C

1) Dodaj SystemConfigurationplatformę do projektu, ale nie martw się o włączenie go w dowolnym miejscu

2) Dodaj wersję Tony Milliona Reachability.hi Reachability.mdo projektu (znalezione tutaj: https://github.com/tonymillion/Reachability )

3) Zaktualizuj sekcję interfejsu

#import "Reachability.h"

// Add this to the interface in the .m file of your view controller
@interface MyViewController ()
{
    Reachability *internetReachableFoo;
}
@end

4) Następnie zaimplementuj tę metodę w pliku m kontrolera widoku, który możesz wywołać

// 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(@"Yayyy, we have the interwebs!");
        });
    };

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

Ważna uwaga:Reachability klasa jest jednym z najczęściej używanych klas w projektach więc może napotkasz nazywania konfliktów z innymi projektami. Jeśli tak się stanie, będziesz musiał zmienić nazwę jednej pary plików Reachability.hi Reachability.mna inną, aby rozwiązać problem.

Uwaga: używana domena nie ma znaczenia. To tylko testowanie bramy do dowolnej domeny.

okradziono mnie
źródło
4
@gonzobrains: Używana domena nie ma znaczenia. To tylko testowanie bramy do dowolnej domeny.
iwasrobbed
3
@KaanDedeoglu To tylko przykład, użyj dowolnej domeny. Po prostu sprawdza bramę do Internetu, a nie, że domena jest faktycznie dostępna.
iwasrobbed
1
Och, przy okazji musisz również dodać SystemConfiguration.frameworkdo projektu (dla metody 1).
wiseindy
2
Użyj www.appleiphonecell.com zamiast google.com - ten adres URL został stworzony przez Apple właśnie z tego powodu.
Smikey,
1
Korzystanie z www.appleiphonecell.com jest teraz (2018) złym wyborem. Teraz przekierowuje do Apple.com, który jest plikiem HTML> 40kB. Powrót do google.com - to tylko 11kB. BTW google.com/m ma ten sam rozmiar, ale według doniesień jest wolniejszy o 120 ms.
BlueskyMed,
310

Lubię upraszczać sprawy. Tak to robię:

//Class.h
#import "Reachability.h"
#import <SystemConfiguration/SystemConfiguration.h>

- (BOOL)connected;

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

Następnie używam tego, gdy chcę sprawdzić, czy mam połączenie:

if (![self connected]) {
    // Not connected
} else {
    // Connected. Do some Internet stuff
}

Ta metoda nie czeka na zmianę statusu sieci w celu wykonania różnych czynności. Po prostu testuje status, kiedy o to poprosisz.

Cannyboy
źródło
Cześć @msec, możesz wypróbować rozwiązanie Andrew Zimmera na tej stronie, działa ono poprawnie z odłączonym
ADSL
1
Dla tych, którzy po prostu kopiują i wklejają tak jak ja z powyższym kodem. Dodaj także SystemConfiguration.framework ręcznie, inaczej pojawi się błąd łączenia.
Iftikhar Ali Ansari
Zawsze łączę się z siecią tak łatwo, jak to możliwe. WiFi nie oznacza, że ​​ma połączenie z Internetem. Chcę zweryfikować połączenie internetowe, nawet jeśli ma ono połączenie WiFi. Czy możesz mi pomóc?
wesley
@wesley Jak to rozwiązałeś?
Keselme
145

Korzystając z kodu osiągalności Apple, stworzyłem funkcję, która sprawdzi to poprawnie bez konieczności dołączania żadnych klas.

Uwzględnij SystemConfiguration.framework w swoim projekcie.

Dokonaj importu:

#import <sys/socket.h>
#import <netinet/in.h>
#import <SystemConfiguration/SystemConfiguration.h>

Teraz wystarczy wywołać tę funkcję:

/*
Connectivity testing code pulled from Apple's Reachability Example: https://developer.apple.com/library/content/samplecode/Reachability
 */
+(BOOL)hasConnectivity {
    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);
    if (reachability != NULL) {
        //NetworkStatus retVal = NotReachable;
        SCNetworkReachabilityFlags flags;
        if (SCNetworkReachabilityGetFlags(reachability, &flags)) {
            if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
            {
                // If target host is not reachable
                return NO;
            }

            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
                return YES;
            }


            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
                    return YES;
                }
            }

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

    return NO;
}

I to iOS 5 przetestowany dla Ciebie.

Andrew Zimmer
źródło
@JezenThomas To nie wykonuje asynchronicznego sprawdzania Internetu, dlatego jest „znacznie szczuplejsze” ... Powinieneś zawsze robić to asynchronicznie, subskrybując powiadomienia, aby nie rozłączać aplikacji w tym procesie.
iwasrobbed
Dzięki, ta praca, nawet jeśli używasz Wi-Fi ADSL i ADSL nie jest podłączony, jest dokładnie tym, czego potrzebuję.
Williew
5
To przecieka pamięć - struktura „czytelności” (obiekt, rzecz) musi zostać uwolniona za pomocą CFRelease ().
Russell Mull,
@ RussellMull ... jakiś pomysł, jak naprawić wyciek?
i_raqz
Dziwne, że ta odpowiedź wyprzedza moją (na pytanie oznaczone jako duplikat) o 2 lata, jest dokładnie taka sama jak moja, ale nigdy jej nie widziałam.
ArtOfWarfare
121

Kiedyś była to poprawna odpowiedź, ale teraz jest nieaktualna, ponieważ zamiast tego należy subskrybować powiadomienia o osiągalności. Ta metoda sprawdza synchronicznie:


Możesz użyć klasy osiągalności Apple. Umożliwi to również sprawdzenie, czy Wi-Fi jest włączone:

Reachability* reachability = [Reachability sharedReachability];
[reachability setHostName:@"www.example.com"];    // Set your host name here
NetworkStatus remoteHostStatus = [reachability remoteHostStatus];

if (remoteHostStatus == NotReachable) { }
else if (remoteHostStatus == ReachableViaWiFiNetwork) { }
else if (remoteHostStatus == ReachableViaCarrierDataNetwork) { }

Klasa osiągalności nie jest dostarczana z zestawem SDK, ale jest częścią tej przykładowej aplikacji Apple . Wystarczy go pobrać i skopiować Reachability.h / m do swojego projektu. Musisz także dodać platformę SystemConfiguration do swojego projektu.

Daniel Rinser
źródło
6
Zobacz mój komentarz powyżej o niestosowaniu takiej dostępności. Używaj go w trybie asynchronicznym i subskrybuj wysyłane powiadomienia - nie.
Kendall Helmstetter Gelner
Ten kod jest dobrym punktem wyjścia dla rzeczy, które należy ustawić, zanim będzie można użyć metod delegowania dla klasy osiągalności.
Brock Woolf
82

Oto bardzo prosta odpowiedź:

NSURL *scriptUrl = [NSURL URLWithString:@"http://www.google.com/m"];
NSData *data = [NSData dataWithContentsOfURL:scriptUrl];
if (data)
    NSLog(@"Device is connected to the Internet");
else
    NSLog(@"Device is not connected to the Internet");

Adres URL powinien wskazywać na bardzo małą stronę internetową. Korzystam z mobilnej witryny Google, ale gdybym miał niezawodny serwer internetowy, przesłałbym mały plik z tylko jednym znakiem dla maksymalnej prędkości.

Jeśli sprawdzanie, czy urządzenie jest w jakiś sposób podłączone do Internetu, jest wszystkim, co chcesz zrobić, zdecydowanie polecam skorzystanie z tego prostego rozwiązania. Jeśli chcesz wiedzieć, w jaki sposób użytkownik jest połączony, skorzystaj z Reachability.

Ostrożnie: spowoduje to krótkie zablokowanie twojego wątku podczas ładowania strony. W moim przypadku nie był to problem, ale powinieneś to rozważyć (podziękowania dla Brada za zwrócenie na to uwagi).

Erik
źródło
10
Naprawdę podoba mi się ten pomysł, ale powiedziałbym, że jeśli chodzi o niezawodność na poziomie 99,999% przy zachowaniu niewielkiego rozmiaru odpowiedzi, przejdź na stronę www.google.com/m, która jest widokiem mobilnym dla google.
rwyland
1
Niesamowite rozwiązanie @Erik. Polecam również korzystanie z www.google.com zamiast www.google.com/m, jak powiedział rwyland. To dziwne, ale z mojego testu wersja mobilna zawsze zajmuje około 120 ms więcej niż www.google.com
Sebyddd
4
Dokumenty Apple zalecają, aby tego nie robić, ponieważ może zablokować wątek w wolnej sieci, może spowodować zakończenie aplikacji w systemie iOS
Brad Thomas
Dziękujemy za pozytywne opinie, zgadzamy się, że www.google.com/m jest najlepszym rozwiązaniem ze względu na niezawodność!
Erik,
3
LOL, jestem pewien, że Google docenia to, że sugerujesz, aby ludzie używali ich jako zasobu do sprawdzania Internetu.
mxcl
73

Oto jak to robię w moich aplikacjach: kod 200 statusu nie gwarantuje niczego, jest dla mnie wystarczająco stabilny. Nie wymaga to tak dużego ładowania, jak zamieszczone tutaj odpowiedzi NSData, ponieważ moje tylko sprawdzają odpowiedź HEAD.

Kod SWIFT

func checkInternet(flag:Bool, completionHandler:(internet:Bool) -> Void)
{
    UIApplication.sharedApplication().networkActivityIndicatorVisible = true

    let url = NSURL(string: "http://www.google.com/")
    let request = NSMutableURLRequest(URL: url!)

    request.HTTPMethod = "HEAD"
    request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
    request.timeoutInterval = 10.0

    NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.mainQueue(), completionHandler:
    {(response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in

        UIApplication.sharedApplication().networkActivityIndicatorVisible = false

        let rsp = response as! NSHTTPURLResponse?

        completionHandler(internet:rsp?.statusCode == 200)
    })
}

func yourMethod()
{
    self.checkInternet(false, completionHandler:
    {(internet:Bool) -> Void in

        if (internet)
        {
            // "Internet" aka Google URL reachable
        }
        else
        {
            // No "Internet" aka Google URL un-reachable
        }
    })
}

Kod celu C

typedef void(^connection)(BOOL);

- (void)checkInternet:(connection)block
{
    NSURL *url = [NSURL URLWithString:@"http://www.google.com/"];
    NSMutableURLRequest *headRequest = [NSMutableURLRequest requestWithURL:url];
    headRequest.HTTPMethod = @"HEAD";

    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration ephemeralSessionConfiguration];
    defaultConfigObject.timeoutIntervalForResource = 10.0;
    defaultConfigObject.requestCachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;

    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue: [NSOperationQueue mainQueue]];

    NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:headRequest
        completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
    {
        if (!error && response)
        {
            block([(NSHTTPURLResponse *)response statusCode] == 200);
        }
    }];
    [dataTask resume];
}

- (void)yourMethod
{
    [self checkInternet:^(BOOL internet)
    {
         if (internet)
         {
             // "Internet" aka Google URL reachable
         }
         else
         {
             // No "Internet" aka Google URL un-reachable
         }
    }];
}
klcjr89
źródło
3
Wydaje się, że to najszybszy sposób
Pavel
3
Uwaga: z mojego doświadczenia wynika, że ​​to rozwiązanie nie działa cały czas. W wielu przypadkach zwrócona odpowiedź wynosi 403 po słodkim czasie. To rozwiązanie wydawało się idealne, ale nie gwarantuje 100% rezultatów.
Mustafa,
10
Od czerwca 2014 r. Nie uda się to w Chinach kontynentalnych, ponieważ chiński rząd całkowicie zablokował google.com. (google.cn działa jednak, ale w Chinach kontynentalnych, bez baidu.com, bez internetu) Prawdopodobnie lepiej pingować na dowolny serwer, z którym chcesz się komunikować.
prewett
4
Zamiast tego użyj www.appleiphonecell.com - właśnie z tego powodu firma Apple utworzyła ten adres URL.
Smikey,
1
Użyłem Appleiphonecell, ponieważ jest on własnością Apple, może być również używany w Chinach i jest to bardzo szybka strona internetowa. To w połączeniu z Twoją odpowiedzią dostarczyło mi najbliższe i najszybsze rozwiązanie. Dziękuję
Septronic,
57

Apple dostarcza przykładowy kod, aby sprawdzić dostępność różnych typów sieci. Alternatywnie istnieje przykład w książce kucharskiej dla programistów iPhone'a.

Uwaga: zapoznaj się z komentarzem @ KHG do tej odpowiedzi na temat wykorzystania kodu osiągalności Apple.

teabot
źródło
Dzięki. Odkryłem, że dokumentacja Xcode w 3.0 zawiera również kod źródłowy, znaleziony przez wyszukanie w dokumentacji „osiągalności”.
Brock Woolf,
7
Należy pamiętać, że nowa wersja (09-08-09) przykładowego kodu Reachability firmy Apple jest asynchroniczna.
Daniel Hepper
46

Możesz użyć Reachabilitydo  ( dostępny tutaj ).

#import "Reachability.h"

- (BOOL)networkConnection {
    return [[Reachability reachabilityWithHostName:@"www.google.com"] currentReachabilityStatus];
}

if ([self networkConnection] == NotReachable) { /* No Network */ } else { /* Network */ } //Use ReachableViaWiFi / ReachableViaWWAN to get the type of connection.
Aleksander Azizi
źródło
@Supertecnoboff Nie, to asynchronizacja.
Aleksander Azizi
39

Apple udostępnia przykładową aplikację, która robi dokładnie to:

Osiągalność

NANNAV
źródło
7
Należy zauważyć, że próbka osiągalności wykrywa tylko, które interfejsy są aktywne, ale nie ma tych, które mają prawidłowe połączenie z Internetem. Aplikacje powinny z gracją radzić sobie z awariami, nawet gdy Reachability zgłosi, że wszystko jest gotowe do pracy.
rpetrich
Na szczęście sytuacja jest znacznie lepsza w 3.0, ponieważ system wyświetli stronę logowania dla użytkowników za zablokowanym Wi-Fi, gdzie musisz się zalogować, aby użyć ... musisz ręcznie sprawdzić przekierowanie (i nadal robisz to w przypadku tworzenia aplikacji 2.2.1)
Kendall Helmstetter Gelner
Nie powiedziałbym, że aplikacja Reachability robi dokładnie to, o co jest poproszony. Jest to jednak dobry punkt wyjścia do dodania żądanej funkcjonalności
Johan Karlsson
Zepsuty link !, byłby wdzięczny, gdyby można to sprawdzić / naprawić,
wielkie
33

Zaktualizowano tylko klasę osiągalności. Możesz teraz użyć:

Reachability* reachability = [Reachability reachabilityWithHostName:@"www.apple.com"];
NetworkStatus remoteHostStatus = [reachability currentReachabilityStatus];

if (remoteHostStatus == NotReachable) { NSLog(@"not reachable");}
else if (remoteHostStatus == ReachableViaWWAN) { NSLog(@"reachable via wwan");}
else if (remoteHostStatus == ReachableViaWiFi) { NSLog(@"reachable via wifi");}
Ben Groot
źródło
1
O ile coś się nie zmieniło od wydania 4.0, kod ten nie jest asynchroniczny i masz gwarancję, że pojawi się on w raportach awarii - zdarzyło mi się to wcześniej.
bpapa
1
Zgadzam się z bpapa. Używanie kodu synchronicznego nie jest dobrym pomysłem. Dzięki za informację
Brock Woolf
25

Jest tutaj ładnie wyglądająca, wykorzystująca ARC i GCD modernizacja osiągalności:

Osiągalność

JK Laiho
źródło
22

Jeśli używasz AFNetworking , możesz użyć własnej implementacji dla statusu dostępności do Internetu.

Najlepszym sposobem na użycie AFNetworkingjest podklasęAFHTTPClient klasy i wykorzystanie tej klasy do wykonywania połączeń sieciowych.

Jedną z zalet korzystania z tego podejścia jest to, że można użyć blocksdo ustawienia pożądanego zachowania, gdy zmienia się status osiągalności. Przypuśćmy, że stworzyłem singletonową podklasę o nazwie AFHTTPClient(jak napisano w „notatkach dotyczących podklasy” w dokumentach AFNetworking ) BKHTTPClient, zrobiłbym coś takiego:

BKHTTPClient *httpClient = [BKHTTPClient sharedClient];
[httpClient setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status)
{
    if (status == AFNetworkReachabilityStatusNotReachable) 
    {
    // Not reachable
    }
    else
    {
        // Reachable
    }
}];

Można również sprawdzić, Wi-Fi lub połączenia WLAN za pomocą specjalnie AFNetworkReachabilityStatusReachableViaWWANi AFNetworkReachabilityStatusReachableViaWiFistałe teksty ( więcej tutaj ).

Bruno Koga
źródło
18

Użyłem kodu w tej dyskusji i wydaje się, że działa dobrze (przeczytaj całość wątek!).

Nie przetestowałem go wyczerpująco z każdym możliwym rodzajem połączenia (np. Ad hoc Wi-Fi).

Feliksyz
źródło
ten kod nie jest całkiem dobry, ponieważ sprawdza, czy masz połączenie Wi-Fi z routerem, a nie czy można uzyskać dostęp do Internetu. Możesz mieć działające Wi-Fi i kontynuować, aby uzyskać dostęp do sieci.
DuckDucking
15

Bardzo proste .... Wypróbuj następujące kroki:

Krok 1: Dodaj SystemConfigurationramę do swojego projektu.


Krok 2: Zaimportuj następujący kod do swojego headerpliku.

#import <SystemConfiguration/SystemConfiguration.h>

Krok 3: Użyj następującej metody

  • Typ 1:

    - (BOOL) currentNetworkStatus {
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        BOOL connected;
        BOOL isConnected;
        const char *host = "www.apple.com";
        SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, host);
        SCNetworkReachabilityFlags flags;
        connected = SCNetworkReachabilityGetFlags(reachability, &flags);
        isConnected = NO;
        isConnected = connected && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired);
        CFRelease(reachability);
        return isConnected;
    }

  • Typ 2:

    Importuj nagłówek :#import "Reachability.h"

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

Krok 4: Jak używać:

- (void)CheckInternet
{
    BOOL network = [self currentNetworkStatus];
    if (network)
    {
        NSLog(@"Network Available");
    }
    else
    {
        NSLog(@"No Network Available");
    }
}
Rajesh Loganathan
źródło
Czy typ 1 jest asynchroniczny?
Supertecnoboff
Chcę poprawek typu 2 z twojej odpowiedzi. Dodałem klasy osiągalności i próbowałem sprawdzić weryfikację połączenia, używając powyższej odpowiedzi. zawsze jest dostępny, nawet jeśli łączę się z Wi-Fi, ale nie ma połączenia z Internetem. WiFi nie oznacza, że ​​ma połączenie z Internetem. Chcę zweryfikować połączenie internetowe, nawet jeśli ma ono połączenie WiFi. Czy możesz mi pomóc?
wesley
12
-(void)newtworkType {

 NSArray *subviews = [[[[UIApplication sharedApplication] valueForKey:@"statusBar"] valueForKey:@"foregroundView"]subviews];
NSNumber *dataNetworkItemView = nil;

for (id subview in subviews) {
    if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) {
        dataNetworkItemView = subview;
        break;
    }
}


switch ([[dataNetworkItemView valueForKey:@"dataNetworkType"]integerValue]) {
    case 0:
        NSLog(@"No wifi or cellular");
        break;

    case 1:
        NSLog(@"2G");
        break;

    case 2:
        NSLog(@"3G");
        break;

    case 3:
        NSLog(@"4G");
        break;

    case 4:
        NSLog(@"LTE");
        break;

    case 5:
        NSLog(@"Wifi");
        break;


    default:
        break;
}
}
Mutawe
źródło
7
Nawet jeśli urządzenie jest podłączone do Wi-Fi lub innej sieci, połączenie internetowe może być nadal niedostępne. Prosty test: podłącz do domowego Wi-Fi, a następnie odłącz modem kablowy. Nadal podłączony do Wi-Fi, ale zero internetu.
iwasrobbed
11
- (void)viewWillAppear:(BOOL)animated
{
    NSString *URL = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com"]];

    return (URL != NULL ) ? YES : NO;
}

Lub użyj klasy Reachability .

Istnieją dwa sposoby sprawdzenia dostępności Internetu za pomocą iPhone SDK:

1. Sprawdź, czy strona Google jest otwarta, czy nie.

2. Klasa osiągalności

Aby uzyskać więcej informacji, zobacz Reachability (Apple Developer).

IOS Rocks
źródło
1
Istnieją dwa sposoby sprawdzenia dostępności Internetu w iPhone SDK 1) Sprawdź, czy strona Google jest otwarta, czy nie.
IOS Rocks
1
-1: Jest to metoda synchroniczna, która blokuje główny wątek (ten, w którym zmienia się interfejs aplikacji) podczas próby połączenia z google.com. Jeśli użytkownik korzysta z bardzo wolnego połączenia danych, telefon zachowa się, jakby proces nie odpowiadał.
iwasrobbed
10

Po pierwsze : dodaj CFNetwork.frameworkw ramach

Kod :ViewController.m

#import "Reachability.h"

- (void)viewWillAppear:(BOOL)animated
{
    Reachability *r = [Reachability reachabilityWithHostName:@"www.google.com"];
    NetworkStatus internetStatus = [r currentReachabilityStatus];

    if ((internetStatus != ReachableViaWiFi) && (internetStatus != ReachableViaWWAN))
    {
        /// Create an alert if connection doesn't work
        UIAlertView *myAlert = [[UIAlertView alloc]initWithTitle:@"No Internet Connection"   message:NSLocalizedString(@"InternetMessage", nil)delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [myAlert show];
        [myAlert release];
    }
    else
    {
         NSLog(@"INTERNET IS CONNECT");
    }
}
Paresh Hirpara
źródło
8

Najpierw pobierz klasę osiągalności i umieść plik reachability.h i reachabilty.m w swoim Xcode .

Najlepszym sposobem jest utworzenie wspólnej klasy Functions (NSObject), aby można było z niej korzystać w dowolnej klasie. Są dwie metody sprawdzania osiągalności połączenia sieciowego:

+(BOOL) reachabiltyCheck
{
    NSLog(@"reachabiltyCheck");
    BOOL status =YES;
    [[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector(reachabilityChanged:)
                                          name:kReachabilityChangedNotification
                                          object:nil];
    Reachability * reach = [Reachability reachabilityForInternetConnection];
    NSLog(@"status : %d",[reach currentReachabilityStatus]);
    if([reach currentReachabilityStatus]==0)
    {
        status = NO;
        NSLog(@"network not connected");
    }
    reach.reachableBlock = ^(Reachability * reachability)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
        });
    };
    reach.unreachableBlock = ^(Reachability * reachability)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
        });
    };
    [reach startNotifier];
    return status;
}

+(BOOL)reachabilityChanged:(NSNotification*)note
{
    BOOL status =YES;
    NSLog(@"reachabilityChanged");
    Reachability * reach = [note object];
    NetworkStatus netStatus = [reach currentReachabilityStatus];
    switch (netStatus)
    {
        case NotReachable:
            {
                status = NO;
                NSLog(@"Not Reachable");
            }
            break;

        default:
            {
                if (!isSyncingReportPulseFlag)
                {
                    status = YES;
                    isSyncingReportPulseFlag = TRUE;
                    [DatabaseHandler checkForFailedReportStatusAndReSync];
                }
            }
            break;
    }
    return status;
}

+ (BOOL) connectedToNetwork
{
    // Create zero addy
    struct sockaddr_in zeroAddress;
    bzero(&zeroAddress, sizeof(zeroAddress));
    zeroAddress.sin_len = sizeof(zeroAddress);
    zeroAddress.sin_family = AF_INET;

    // Recover reachability flags
    SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
    SCNetworkReachabilityFlags flags;
    BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
    CFRelease(defaultRouteReachability);
    if (!didRetrieveFlags)
    {
        NSLog(@"Error. Could not recover network reachability flags");
        return NO;
    }
    BOOL isReachable = flags & kSCNetworkFlagsReachable;
    BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
    BOOL nonWiFi = flags & kSCNetworkReachabilityFlagsTransientConnection;
    NSURL *testURL = [NSURL URLWithString:@"http://www.apple.com/"];
    NSURLRequest *testRequest = [NSURLRequest requestWithURL:testURL  cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];
    NSURLConnection *testConnection = [[NSURLConnection alloc] initWithRequest:testRequest delegate:self];
    return ((isReachable && !needsConnection) || nonWiFi) ? (testConnection ? YES : NO) : NO;
}

Teraz możesz sprawdzić połączenie sieciowe w dowolnej klasie, wywołując tę ​​metodę klasy.

Latika Tiwari
źródło
8

Istnieje również inna metoda sprawdzania połączenia internetowego za pomocą iPhone SDK.

Spróbuj zaimplementować następujący kod dla połączenia sieciowego.

#import <SystemConfiguration/SystemConfiguration.h>
#include <netdb.h>

/**
     Checking for network availability. It returns
     YES if the network is available.
*/
+ (BOOL) connectedToNetwork
{

    // Create zero addy
    struct sockaddr_in zeroAddress;
    bzero(&zeroAddress, sizeof(zeroAddress));
    zeroAddress.sin_len = sizeof(zeroAddress);
    zeroAddress.sin_family = AF_INET;

    // Recover reachability flags
    SCNetworkReachabilityRef defaultRouteReachability =
        SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
    SCNetworkReachabilityFlags flags;

    BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
    CFRelease(defaultRouteReachability);

    if (!didRetrieveFlags)
    {
        printf("Error. Could not recover network reachability flags\n");
        return NO;
    }

    BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0);
    BOOL needsConnection = ((flags & kSCNetworkFlagsConnectionRequired) != 0);

    return (isReachable && !needsConnection) ? YES : NO;
}
Sahil Mahajan
źródło
8
  1. Pobierz plik osiągalności, https://gist.github.com/darkseed/1182373

  2. I dodaj CFNetwork.frameworki „SystemConfiguration.framework” w ramach

  3. Wykonaj #import „Reachability.h”


Po pierwsze : dodaj CFNetwork.frameworkw ramach

Kod :ViewController.m

- (void)viewWillAppear:(BOOL)animated
{
    Reachability *r = [Reachability reachabilityWithHostName:@"www.google.com"];
    NetworkStatus internetStatus = [r currentReachabilityStatus];

    if ((internetStatus != ReachableViaWiFi) && (internetStatus != ReachableViaWWAN))
    {
        /// Create an alert if connection doesn't work
        UIAlertView *myAlert = [[UIAlertView alloc]initWithTitle:@"No Internet Connection"   message:NSLocalizedString(@"InternetMessage", nil)delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [myAlert show];
        [myAlert release];
    }
    else
    {
         NSLog(@"INTERNET IS CONNECT");
    }
}
Maulik Salvi
źródło
8

Swift 3 / Swift 4

Musisz najpierw zaimportować

import SystemConfiguration

Możesz sprawdzić połączenie internetowe następującą metodą

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)

}
Devang Tandel
źródło
7

Klasa osiągalności jest OK, aby dowiedzieć się, czy połączenie internetowe jest dostępne na urządzeniu, czy nie ...

Ale w przypadku dostępu do zasobu intranetowego :

Pingowanie serwera intranetowego za pomocą klasy osiągalności zawsze zwraca wartość true.

Tak więc szybkim rozwiązaniem w tym scenariuszu byłoby utworzenie metody internetowej wywoływanej pingmewraz z innymi metodami sieciowymi w usłudze. pingmePowinien powrócić coś.

Napisałem więc następującą metodę dotyczącą popularnych funkcji

-(BOOL)PingServiceServer
{
    NSURL *url=[NSURL URLWithString:@"http://www.serveraddress/service.asmx/Ping"];

    NSMutableURLRequest *urlReq=[NSMutableURLRequest requestWithURL:url];

    [urlReq setTimeoutInterval:10];

    NSURLResponse *response;

    NSError *error = nil;

    NSData *receivedData = [NSURLConnection sendSynchronousRequest:urlReq
                                                 returningResponse:&response
                                                             error:&error];
    NSLog(@"receivedData:%@",receivedData);

    if (receivedData !=nil)
    {
        return YES;
    }
    else
    {
        NSLog(@"Data is null");
        return NO;
    }
}

Powyższa metoda była dla mnie bardzo przydatna, dlatego za każdym razem, gdy próbuję wysłać dane do serwera, zawsze sprawdzam dostępność mojego zasobu intranetowego przy użyciu tego żądania URLR o niskim limicie czasu.

Durai Amuthan.H
źródło
7

Wykonanie tego samemu jest niezwykle proste. Działa następująca metoda. Pamiętaj tylko, aby nie dopuścić do przekazania protokołu nazwy hosta, takiego jak HTTP, HTTPS itp., Wraz z nazwą.

-(BOOL)hasInternetConnection:(NSString*)urlAddress
{
    SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [urlAddress UTF8String]);
    SCNetworkReachabilityFlags flags;
    if (!SCNetworkReachabilityGetFlags(ref, &flags))
    {
        return NO;
    }
    return flags & kSCNetworkReachabilityFlagsReachable;
}

Jest szybki, prosty i bezbolesny.

Tony
źródło
7

Myślę, że to najlepsza odpowiedź.

„Tak” oznacza podłączony. „Nie” oznacza rozłączony.

#import "Reachability.h"

 - (BOOL)canAccessInternet
{
    Reachability *IsReachable = [Reachability reachabilityForInternetConnection];
    NetworkStatus internetStats = [IsReachable currentReachabilityStatus];

    if (internetStats == NotReachable)
    {
        return NO;
    }
    else
    {
        return YES;
    }
}
Mina Fawzy
źródło
6

Zaimportuj Reachable.hklasę do swojego ViewControlleri użyj następującego kodu, aby sprawdzić łączność :

     #define hasInternetConnection [[Reachability reachabilityForInternetConnection] isReachable]
     if (hasInternetConnection){
           // To-do block
     }
Himanshu Mahajan
źródło
Twoja odpowiedź jest dokładnie tym, czego szukam. Pan zasługuje na głos w górę xD
Nikel Arteta
Nie działa, jeśli masz połączenie z Wi-Fi bez Internetu.
Keselme,
6
  • Krok 1: Dodaj klasę osiągalności w swoim projekcie.
  • Krok 2: Zaimportuj klasę osiągalności
  • Krok 3: Utwórz poniższą funkcję

    - (BOOL)checkNetConnection {
        self.internetReachability = [Reachability reachabilityForInternetConnection];
        [self.internetReachability startNotifier];
        NetworkStatus netStatus = [self.internetReachability currentReachabilityStatus];
        switch (netStatus) {
            case NotReachable:
            {
                return NO;
            }
    
            case ReachableViaWWAN:
            {
                 return YES;
            }
    
            case ReachableViaWiFi:
            {
                 return YES;
            }
        }
    }
  • Krok 4: Wywołaj funkcję jak poniżej:

    if (![self checkNetConnection]) {
        [GlobalFunctions showAlert:@""
                         message:@"Please connect to the Internet!"
                         canBtntitle:nil
                         otherBtnTitle:@"Ok"];
        return;
    }
    else
    {
        Log.v("internet is connected","ok");
    }
Anny
źródło
Dokumenty
noobsmcgoobs