[ios] iOS에서 인터넷 연결을 감지하는 가장 쉬운 방법은 무엇입니까?

나는이 질문이 다른 많은 사람들의 속임수 인 것처럼 보이지만 간단한 사례가 여기에 잘 설명되어 있다고 생각하지 않습니다. HTTPUrlConnection사용 가능한 연결이없는 경우 Android 및 BlackBerry 배경에서 가져와 요청을 즉시 실패하게합니다. 이것은 완전히 제정신의 행동처럼 보이고, NSURLConnectioniOS에서 그것을 모방하지 않았다는 사실에 놀랐 습니다.

Apple (및 Apple을 확장 한 다른 사람들) Reachability은 네트워크 상태를 결정하는 데 도움이 되는 수업을 제공한다는 것을 이해합니다 . 나는 이것을 처음으로보고 기뻤고와 같은 것을 완전히 기대 bool isNetworkAvailable()했지만 놀랍게도 알림 등록 및 콜백이 필요한 복잡한 시스템과 불필요한 것으로 보이는 세부 정보가 필요했습니다. 더 좋은 방법이 있어야합니다.

내 앱은 이미 연결되지 않은 것을 포함하여 연결 실패를 정상적으로 처리합니다. 사용자에게 실패 알림이 표시되고 앱이 계속 진행됩니다.

따라서 내 요구 사항은 간단합니다. 단일 동기 함수 모든 HTTP 요청 전에 호출하여 실제로 요청을 보내는 것을 방해해야하는지 여부를 결정할 수 있습니다. 이상적으로는 설정이 필요 없으며 부울 만 반환합니다.

iOS에서는 이것이 실제로 불가능합니까?



답변

좀 더 연구를하고 더 최신 솔루션으로 답변을 업데이트하고 있습니다. 이미 살펴 보았는지 확실하지 않지만 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를 추가하는 것을 잊지 마십시오.


답변

이 스레드 가이 유형의 질문에 대한 최고의 Google 결과이므로, 나에게 맞는 솔루션을 제공 할 것이라고 생각했습니다. 이미 AFNetworking을 사용 하고 있었지만 검색 과정에서 프로젝트 중반까지 AFNetworking으로이 작업을 수행하는 방법이 밝혀지지 않았습니다.

당신이 원하는 것은
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;
    }

}];

다음을 사용하여 도달 가능성을 동 기적으로 테스트 할 수도 있습니다 (한 번 모니터링이 시작된 경우).

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


답변

너무 늦게 답변 해 주셔서 죄송하지만이 답변이 향후 누군가에게 도움이 되었기를 바랍니다.

다음은 추가 클래스없이 인터넷 연결을 확인할 수있는 작은 네이티브 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
    }


답변

현재 프로젝트 또는 대리자에 추가 파일이 필요없는이 간단한 동기 방법을 사용하고 있습니다.

수입:

#import <SystemConfiguration/SCNetworkReachability.h>

이 메소드를 작성하십시오.

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

그런 다음에 이것을 넣으면 MyNetworkClass:

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

시뮬레이터에서 테스트하는 경우 Mac의 Wi-Fi를 켜거나 끄면 시뮬레이터가 전화 설정을 무시합니다.

최신 정보:

  1. 결국 메인 스레드를 차단하지 않기 위해 스레드 / 비동기 콜백을 사용했습니다. 정기적으로 다시 테스트하여 캐시 된 결과를 사용할 수 있습니다. 데이터 연결을 불필요하게 열어 두지 않아야합니다.

  2. @thunk가 설명했듯이 Apple이 사용하는 더 나은 URL을 사용할 수 있습니다. http://cadinc.com/blog/why-your-apple-ios-7-device-wont-connect-to-the-wifi-network


답변

구현이 끝났을 때 살펴보면 정말 간단합니다. 다시 한 번, 매우 간단합니다. 필요한 유일한 항목은 두 가지 부울 변수뿐입니다. 인터넷 연결성과 호스트 연결성 ). 연결 상태를 결정할 수있는 도우미 클래스를 구성한 후에는 이러한 절차를 알기 위해 필요한 구현을 다시 신경 쓰지 않아도됩니다.

예:

#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


답변

누군가가 있다 전에 간단한, 재사용 가능한 방법으로이 문제를 해결했다. DDGReachability.

편집 : 또는 tonymillion/Reachability.


답변

코드를 추출하여 하나의 단일 방법에 넣었습니다. 다른 방법이 도움이되기를 바랍니다.

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


}