[ios] iOS 또는 macOS에서 활성 인터넷 연결을 확인하는 방법은 무엇입니까?

Cocoa Touch를 사용하여 iOS에서 인터넷에 연결되어 있는지 확인하고 싶습니다. 라이브러리를 또는 Cocoa 라이브러리를 사용하는 macOS .

나는 이것을 사용하여 이것을 수행하는 방법을 생각해 냈습니다 NSURL. 내가 한 방식은 약간 신뢰할 수없는 것 같습니다 (Google조차도 언젠가 다운되어 타사에 의존 할 수 있기 때문에 나쁜 것 같습니다) .Google이 응답하지 않으면 다른 웹 사이트의 응답을 확인할 수 있지만 내 응용 프로그램에서 낭비되고 불필요한 오버 헤드로 보입니다.

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

내가 한 일이 잘못 stringWithContentsOfURL되었습니까 (iOS 3.0 및 macOS 10.4에서는 더 이상 사용되지 않습니다) 그렇다면 그렇게하는 더 좋은 방법은 무엇입니까?



답변

중요 :이 점검은 항상 비동기 적으로 수행 해야합니다 . 아래 답변의 대부분은 동기식이므로 그렇지 않으면 앱이 중지됩니다.


빠른

1) CocoaPods 또는 Carthage를 통해 설치 하십시오 : https://github.com/ashleymills/Reachability.swift

2) 폐쇄를 통한 접근성 테스트

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

목표 -C

1) SystemConfiguration프로젝트에 프레임 워크를 추가 하지만 어디서나 포함시키는 것에 대해 걱정하지 마십시오.

2)의 토니 만의 버전을 추가 Reachability.h하고 Reachability.m프로젝트에 (여기 : https://github.com/tonymillion/Reachability )

3) 인터페이스 섹션 업데이트

#import "Reachability.h"

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

4) 그런 다음이 메소드를 호출 할 수있는 뷰 컨트롤러의 .m 파일에 구현하십시오.

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

중요 참고 :Reachability 다른 프로젝트와 이름 충돌로 실행할 수 있도록 클래스를 프로젝트에 가장 많이 사용되는 클래스 중 하나입니다. 이 경우, 당신은 쌍 중 하나의 이름을 변경해야 Reachability.h하고Reachability.m 문제를 해결하려면 파일 파일 합니다.

참고 : 사용 하는 도메인은 중요하지 않습니다. 모든 도메인에 대한 게이트웨이를 테스트하고 있습니다.


답변

나는 일을 단순하게 유지하고 싶다. 내가하는 방법은 다음과 같습니다.

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

그런 다음 연결이 있는지 확인할 때마다 이것을 사용합니다.

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

이 방법은 네트워크 상태가 변경 될 때까지 기다리지 않습니다. 요청하면 상태 만 테스트합니다.


답변

Apple의 접근성 코드를 사용하여 클래스를 포함하지 않고도이를 올바르게 확인할 수있는 기능을 만들었습니다.

프로젝트에 SystemConfiguration.framework를 포함하십시오.

가져 오기 :

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

이제이 함수를 호출하십시오.

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

그리고 그것은 당신을 위해 테스트 된 iOS 5 입니다.


답변

이것은 정답 이었지만 지금은 도달 가능성에 대한 알림을 구독해야하므로 구식입니다. 이 방법은 동 기적으로 확인합니다.


Apple의 Reachability 클래스를 사용할 수 있습니다. 또한 Wi-Fi가 활성화되어 있는지 확인할 수 있습니다.

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

연결성 클래스는 SDK와 함께 제공되지 않고이 Apple 샘플 응용 프로그램 의 일부입니다 . 다운로드하여 프로젝트에 Reachability.h / m을 복사하십시오. 또한 프로젝트에 SystemConfiguration 프레임 워크를 추가해야합니다.


답변

다음은 매우 간단한 답변입니다.

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");

URL은 매우 작은 웹 사이트를 가리켜 야합니다. 여기에서는 Google의 모바일 웹 사이트를 사용하지만 신뢰할 수있는 웹 서버가있는 경우 최대 속도를 위해 문자가 하나만있는 작은 파일을 업로드 했습니다 .

장치가 어떻게 든 인터넷에 연결되어 있는지 확인하는 것이 원하는 모든 것이라면이 간단한 솔루션을 사용하는 것이 좋습니다. 사용자의 연결 방법을 알아야하는 경우 도달 가능성을 사용하는 것이 좋습니다.

주의 : 스레드가 웹 사이트를로드하는 동안 스레드가 잠시 차단됩니다. 내 경우에는 이것이 문제가되지 않았지만 이것을 고려해야합니다 (브래드가 이것을 지적한 것에 대한 신용).


답변

내 앱에서 수행하는 방법은 다음과 같습니다. 200 상태 응답 코드는 아무것도 보장하지 않지만 충분히 안정적입니다. 내 HEAD 응답을 확인하기 때문에 여기에 게시 된 NSData 답변만큼 많은로드가 필요하지 않습니다.

스위프트 코드

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

오브젝티브 -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
         }
    }];
}


답변

Apple 은 다양한 유형의 네트워크 가용성을 확인하기 위해 샘플 코드 를 제공 합니다. 또는 iPhone 개발자 요리 책에 예가 있습니다.

참고 : Apple의 접근성 코드 사용에 대한이 답변에 대한 @KHG의 의견을 참조하십시오.