จะตรวจสอบการเชื่อมต่ออินเทอร์เน็ตที่ใช้งานบน iOS หรือ macOS ได้อย่างไร?


1325

ฉันต้องการตรวจสอบเพื่อดูว่าฉันมีการเชื่อมต่ออินเทอร์เน็ตบน iOS โดยใช้ไลบรารีCocoa Touchหรือบน macOS โดยใช้ห้องสมุดCocoa

NSURLฉันมาด้วยวิธีการที่จะทำเช่นนี้ต่อ A วิธีที่ฉันทำดูเหมือนจะไม่น่าเชื่อถือเลยสักนิด (เพราะแม้กระทั่ง 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) และถ้าเป็นเช่นนั้นเป็นวิธีที่ดีกว่าที่จะบรรลุสิ่งนี้?


11
ค่อนข้างreturn (BOOL)URLString;หรือดีกว่าreturn !!URLStringหรือreturn URLString != nil

3
ฉันไม่ทราบว่ากรณีการใช้งานของคุณคืออะไร แต่ถ้าคุณสามารถลองใช้คำขอและจัดการข้อผิดพลาดใด ๆ เช่นการขาดการเชื่อมต่อที่เกิดขึ้น หากคุณไม่สามารถทำสิ่งนี้ได้มีคำแนะนำที่ดีมากมายในกรณีนี้
SK9

2
ทางออกของคุณฉลาดและฉันชอบมาก คุณยังสามารถใช้ NSString *URLString = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"https://twitter.com/getibox"] encoding:NSUTF8StringEncoding error:nil];เพื่อกำจัดคำเตือนที่น่ารำคาญ
Abdelrahman Eid

4
ลองใช้ระดับการเข้าถึงได้จากลิงค์ด้านล่างมันจะทำงานให้คุณ github.com/tonymillion/ การเข้าถึง
Dhaval H. Nena

4
สำหรับผู้ที่เพิ่งพบคำตอบนี้: stackoverflow.com/a/8813279
afollestad

คำตอบ:


1284

สำคัญ : การตรวจสอบนี้ควรเสมอจะดำเนินการถ่ายทอดสด คำตอบส่วนใหญ่ด้านล่างเป็นแบบซิงโครนัสดังนั้นโปรดระมัดระวังมิฉะนั้นคุณจะทำให้แอปของคุณค้าง


รวดเร็ว

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

Objective-C

1) เพิ่มSystemConfigurationกรอบการทำงานให้กับโครงการ แต่ไม่ต้องกังวลกับการรวมไว้ที่ใดก็ได้

2) เพิ่มรุ่นของ Tony ล้าน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ไฟล์เป็นอย่างอื่นเพื่อแก้ไขปัญหา

หมายเหตุ:โดเมนที่คุณใช้ไม่สำคัญ มันแค่ทดสอบหาเกตเวย์ไปยังโดเมนใด ๆ


4
@gonzobrains: โดเมนที่คุณใช้ไม่สำคัญ มันแค่ทดสอบหาเกตเวย์ไปยังโดเมนใด ๆ
iwasrobbed

3
@KaanDedeoglu มันเป็นเพียงตัวอย่างใช้โดเมนอะไรก็ได้ที่คุณต้องการ เพียงตรวจสอบเกตเวย์ไปยังอินเทอร์เน็ตไม่ใช่ว่าโดเมนนั้นมีอยู่จริง
iwasrobbed

1
โอ้คุณต้องเพิ่มSystemConfiguration.frameworkเข้าไปในโครงการด้วย (สำหรับวิธีที่ 1)
ปัญญา

2
ใช้ www.appleiphonecell.com แทน google.com - URL นี้สร้างโดย apple ด้วยเหตุผลนี้
Smikey

1
การใช้ www.appleiphonecell.com ตอนนี้ (2018) เป็นตัวเลือกที่ไม่ดี ตอนนี้จะเปลี่ยนเส้นทางไปยัง Apple.com ซึ่งเป็นไฟล์> 40kB html กลับไปที่ google.com - เพียง 11kB BTW google.com/m มีขนาดเท่ากัน แต่มีรายงานว่าช้ากว่า 120 msec
BlueskyMed

310

ฉันชอบทำสิ่งต่าง ๆ ให้เรียบง่าย วิธีที่ฉันทำคือ:

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

วิธีนี้ไม่รอสถานะเครือข่ายที่เปลี่ยนแปลงเพื่อทำสิ่งต่างๆ มันแค่ทดสอบสถานะเมื่อคุณถามมัน


สวัสดี @ msec คุณสามารถลองใช้วิธีแก้ปัญหา Andrew Zimmer ในหน้านี้มันทำงานได้ดีกับการเชื่อมต่อ adsl (และเชื่อมต่อ wifi)
Williew

1
สำหรับผู้ที่เพิ่งคัดลอกและวางอย่างที่ฉันทำด้วยรหัสด้านบน นอกจากนี้ยังเพิ่ม SystemConfiguration.framework ด้วยตนเองหรือคุณจะได้รับการเชื่อมโยงข้อผิดพลาด
Iftikhar Ali Ansari

เข้าถึงได้เสมอถ้าฉันเชื่อมต่อกับ WiFi WiFi ไม่ได้หมายความว่ามีการเชื่อมต่ออินเทอร์เน็ต ฉันต้องการตรวจสอบการเชื่อมต่ออินเทอร์เน็ตแม้จะมีการเชื่อมต่อ WiFi คุณช่วยฉันออกได้ไหม
wesley

@wesley คุณแก้ปัญหาได้อย่างไร?
Keselme

145

ด้วยการใช้รหัสความสามารถในการเข้าถึงข้อมูลของ 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 ที่ผ่านการทดสอบสำหรับคุณแล้ว


@JezenThomas นี่ไม่ได้ทำการตรวจสอบอินเทอร์เน็ตแบบอะซิงโครนัสซึ่งเป็นสาเหตุว่าทำไม "slimmer มาก" ... คุณควรทำแบบอะซิงโครนัสโดยสมัครรับการแจ้งเตือนเพื่อที่คุณจะไม่วางสายในกระบวนการนี้
iwasrobbed

ขอบคุณงานนี้แม้ว่าคุณจะใช้ wifi adsl และ adsl ไม่ได้เชื่อมต่อเป็นสิ่งที่ฉันต้องการ
Williew

5
หน่วยความจำรั่วนี้ - โครงสร้าง 'ความสามารถในการอ่าน' (วัตถุ, สิ่งของ) ต้องได้รับการปลดปล่อยด้วย CFRelease ()
Russell Mull

@RussellMull ... ความคิดใด ๆ วิธีการแก้ไขการรั่วไหล?
i_raqz

แปลกที่คำตอบนี้มาถึงฉัน (ในคำถามที่ทำเครื่องหมายว่าซ้ำกัน) ภายใน 2 ปีก็เหมือนกับฉัน แต่ฉันไม่เคยเห็นมาก่อนจนถึงทุกวันนี้
ArtOfWarfare

121

สิ่งนี้เคยเป็นคำตอบที่ถูกต้อง แต่ตอนนี้ล้าสมัยแล้วเนื่องจากคุณควรสมัครรับการแจ้งเตือนเพื่อความสะดวกในการเข้าถึงแทน วิธีนี้ตรวจสอบแบบซิงโครนัส:


คุณสามารถใช้คลาสการเข้าถึงของ Apple นอกจากนี้ยังจะช่วยให้คุณตรวจสอบว่าเปิดใช้งาน 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) { }

ชั้น reachability ไม่ได้มาพร้อมกับ SDK แต่เป็นส่วนหนึ่งของโปรแกรมนี้ตัวอย่างแอปเปิ้ล เพียงดาวน์โหลดและคัดลอก Reachability.h / m ไปยังโครงการของคุณ นอกจากนี้คุณต้องเพิ่มกรอบการทำงานของ SystemConfiguration เข้ากับโครงการของคุณ


6
ดูความคิดเห็นของฉันด้านบนเกี่ยวกับการไม่ใช้การเข้าถึงเช่นนั้น ใช้ในโหมดอะซิงโครนัสและสมัครรับการแจ้งเตือนที่ส่ง - ไม่
Kendall Helmstetter Gelner

รหัสนี้เป็นจุดเริ่มต้นที่ดีสำหรับสิ่งที่คุณต้องตั้งค่าก่อนที่คุณจะสามารถใช้วิธีการมอบสิทธิ์สำหรับคลาสที่เข้าถึงได้
s ของ

82

นี่คือคำตอบที่ง่ายมาก:

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 ที่นี่ แต่ถ้าฉันมีเว็บเซิร์ฟเวอร์ที่เชื่อถือได้ฉันจะอัปโหลดไฟล์ขนาดเล็กที่มีเพียงหนึ่งตัวอักษรในนั้นเพื่อความเร็วสูงสุด

หากตรวจสอบว่าอุปกรณ์ที่มีอย่างใดเชื่อมต่อกับอินเทอร์เน็ตเป็นทุกสิ่งที่คุณต้องการจะทำแน่นอนผมอยากแนะนำให้ใช้วิธีนี้ง่าย หากคุณต้องการทราบว่าผู้ใช้เชื่อมต่อกันอย่างไรการใช้การเข้าถึงได้นั้นเป็นวิธีที่ควรทำ

ระวัง: นี่จะบล็อกเธรดของคุณสั้น ๆ ในขณะที่โหลดเว็บไซต์ ในกรณีของฉันนี่ไม่ใช่ปัญหา แต่คุณควรพิจารณาเรื่องนี้ (เครดิตกับแบรดสำหรับการชี้เรื่องนี้)


10
ฉันชอบความคิดนี้จริงๆ แต่ฉันอยากจะพูดถึงความน่าเชื่อถือ 99.999% ในขณะที่รักษาขนาดการตอบสนองไว้เพียงเล็กน้อยให้ไปที่ www.google.com/m ซึ่งเป็นมุมมองอุปกรณ์พกพาสำหรับ google
rwyland

1
โซลูชั่นที่ยอดเยี่ยม @Erik สิ่งที่ฉันขอแนะนำให้คุณใช้คือ www.google.com แทนที่จะเป็น www.google.com/m ตามที่ rwyland กล่าว มันแปลก แต่จากการทดสอบของฉันเวอร์ชั่นมือถือใช้เวลามากกว่า 120 วินาทีมากกว่า www.google.com
Sebyddd

4
เอกสารของ Apple ไม่แนะนำให้ทำเช่นนี้เพราะสามารถบล็อกเธรดบนเครือข่ายที่ช้าอาจทำให้แอปถูกยกเลิกใน iOS
Brad Thomas

ขอขอบคุณสำหรับข้อเสนอแนะในเชิงบวกยอมรับว่า www.google.com/m เป็นทางออกที่ดีที่สุดเนื่องจากความน่าเชื่อถือ!
Erik

3
ฮ่า ๆ ฉันมั่นใจว่า Google ขอขอบคุณที่คุณแนะนำให้ผู้คนใช้พวกเขาเป็นแหล่งตรวจสอบทางอินเทอร์เน็ต
mxcl

73

นี่คือวิธีที่ฉันทำในแอพของฉัน: ในขณะที่รหัสตอบกลับสถานะ 200 ไม่รับประกันอะไรเลย แต่ก็มีความเสถียรพอสำหรับฉัน สิ่งนี้ไม่จำเป็นต้องโหลดเท่าคำตอบ NSData ที่โพสต์ที่นี่เพราะของฉันจะตรวจสอบการตอบสนองของ HEAD

รหัสสวิฟท์

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

3
ดูเหมือนว่านี่เป็นวิธีที่เร็วที่สุด
Pavel

3
ข้อควรระวัง: จากประสบการณ์ของฉันวิธีนี้ไม่ได้ผลตลอดเวลา ในหลายกรณีการตอบสนองที่ส่งคืนคือ 403 หลังจากใช้เวลาที่น่าพอใจ วิธีนี้ดูเหมือนสมบูรณ์แบบ แต่ไม่รับประกันผลลัพธ์ 100%
มุสตาฟา

10
เมื่อวันที่มิถุนายน 2014 สิ่งนี้จะล้มเหลวในจีนแผ่นดินใหญ่เนื่องจากรัฐบาลจีนได้ปิดกั้น google.com อย่างสมบูรณ์แล้ว (google.cn ทำงานได้ แต่ในจีนแผ่นดินใหญ่ไม่มี baidu.com ไม่มีอินเทอร์เน็ต) น่าจะดีกว่าที่จะ ping เซิร์ฟเวอร์ใด ๆ ก็ตามที่คุณจำเป็นต้องสื่อสารด้วย
prewett

4
ใช้ www.appleiphonecell.com แทน - apple สร้าง url นี้ด้วยเหตุผลนี้
Smikey

1
ฉันใช้appleiphonecellเนื่องจากเป็นของ Apple เองสามารถใช้ในจีนได้เช่นกันและเป็นเว็บไซต์ที่รวดเร็วมาก สิ่งนี้ประกอบกับคำตอบของคุณทำให้ฉันได้รับโซลูชั่นที่ใกล้ที่สุดและเร็วที่สุด ขอบคุณ
ก.ย.

57

Apple ระบุรหัสตัวอย่างเพื่อตรวจสอบความพร้อมใช้งานเครือข่ายประเภทต่างๆ หรือมีตัวอย่างในตำรานักพัฒนา iPhone

หมายเหตุ:โปรดดูความคิดเห็นของ @ KHG ในคำตอบนี้เกี่ยวกับการใช้รหัสการเข้าถึงของ Apple


ขอบคุณ ฉันค้นพบว่าเอกสาร Xcode ใน 3.0 ยังมีซอร์สโค้ดซึ่งพบได้โดยการค้นหา "การเข้าถึง" ในเอกสาร
Brock Woolf

7
โปรดทราบว่าการแก้ไขใหม่ (09-08-09) ของโค้ดตัวอย่างความสามารถเข้าถึงได้จาก Apple นั้นเป็นแบบอะซิงโครนัส
Daniel Hepper

46

คุณสามารถใช้Reachability ( ใช้ได้ที่นี่ )

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

@Supertecnoboff ไม่มันเป็น async
Aleksander Azizi

39

Apple มีแอปตัวอย่างซึ่งทำสิ่งนี้ทุกประการ:

reachability


7
คุณควรทราบว่าตัวอย่างความสามารถเข้าถึงได้ตรวจพบว่ามีการใช้งานอินเทอร์เฟซใดบ้าง แต่ไม่มีการเชื่อมต่อที่ถูกต้องกับอินเทอร์เน็ต แอปพลิเคชันควรจัดการกับความล้มเหลวอย่างสง่างามแม้เมื่อรายงานความสามารถเข้าถึงได้ว่าทุกอย่างพร้อมใช้งาน
rpetrich

อย่างมีความสุขสถานการณ์ดีขึ้นมากใน 3.0 เนื่องจากระบบจะแสดงหน้าเข้าสู่ระบบสำหรับผู้ใช้ที่อยู่หลัง WiFi ที่ถูกล็อคซึ่งคุณต้องเข้าสู่ระบบเพื่อใช้ ... คุณใช้เพื่อตรวจสอบการเปลี่ยนเส้นทางด้วยตนเอง (และคุณยังคงทำ ถ้าพัฒนาแอพ 2.2.1)
Kendall Helmstetter Gelner

ฉันจะไม่พูดว่าแอพสำหรับการเข้าถึงนั้นทำสิ่งที่ร้องขอ อย่างไรก็ตามมันเป็นจุดเริ่มต้นที่ดีสำหรับการเพิ่มประเภทของฟังก์ชั่นที่ต้องการ
Johan Karlsson

ลิงค์เสีย!, จะขอบคุณถ้าสิ่งนี้สามารถตรวจสอบ / คงที่ขอบคุณมาก
Heider Sati

33

อัปเดตเฉพาะคลาสการเข้าถึงได้เท่านั้น ตอนนี้คุณสามารถใช้:

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

1
ยกเว้นว่ามีการเปลี่ยนแปลงบางอย่างตั้งแต่เปิดตัว 4.0 รหัสนั้นไม่ได้เป็นแบบอะซิงโครนัสและคุณรับประกันได้ว่าจะปรากฏใน Crash Reports - เกิดขึ้นกับฉันมาก่อน
bpapa

1
ฉันเห็นด้วยกับ bpapa ไม่ใช่ความคิดที่ดีที่จะใช้รหัสซิงโครนัส ขอบคุณสำหรับข้อมูลแม้ว่า
Brock Woolf



22

หากคุณกำลังใช้ AFNetworkingคุณสามารถใช้การดำเนินการของตัวเองสำหรับสถานะการเข้าถึงอินเทอร์เน็ต

วิธีที่ดีที่สุดAFNetworkingคือใช้subclassAFHTTPClientและใช้คลาสนี้เพื่อทำการเชื่อมต่อเครือข่ายของคุณ

ข้อดีอย่างหนึ่งของการใช้วิธีนี้คือคุณสามารถใช้blocksเพื่อตั้งค่าลักษณะการทำงานที่ต้องการเมื่อมีการเปลี่ยนแปลงสถานะการเข้าถึง สมมติว่าฉันได้สร้าง subclass เดี่ยวของAFHTTPClient(ตามที่กล่าวไว้ใน "Subclassing notes" ในAFNetworking docs ) ชื่อBKHTTPClientฉันจะทำสิ่งที่ชอบ:

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

คุณสามารถตรวจสอบการเชื่อมต่อ Wi-Fi หรือ WLAN โดยเฉพาะโดยใช้AFNetworkReachabilityStatusReachableViaWWANและAFNetworkReachabilityStatusReachableViaWiFienums ( เพิ่มเติมได้ที่นี่ )


18

ฉันใช้รหัสในการสนทนานี้และดูเหมือนว่าจะทำงานได้ดี (อ่านทั้งหมดเธรด !)

ฉันไม่ได้ทดสอบอย่างละเอียดถี่ถ้วนกับการเชื่อมต่อทุกประเภทที่เป็นไปได้ (เช่นเฉพาะกิจ Wi-Fi)


รหัสนี้ไม่ดีอย่างสิ้นเชิงเพราะเพียงตรวจสอบว่าคุณมีการเชื่อมต่อ wifi กับเราเตอร์หรือไม่หากสามารถเข้าถึงเว็บได้ คุณสามารถใช้งาน wifi ได้และเปิดใช้งานการเข้าถึงเว็บต่อไป
DuckDucking

15

ง่ายมาก .... ลองขั้นตอนเหล่านี้:

ขั้นตอนที่ 1:เพิ่มSystemConfigurationกรอบงานในโครงการของคุณ


ขั้นตอนที่ 2:นำเข้ารหัสต่อไปนี้ลงในheaderไฟล์ของคุณ

#import <SystemConfiguration/SystemConfiguration.h>

ขั้นตอนที่ 3:ใช้วิธีการต่อไปนี้

  • ประเภท 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;
    }

  • ประเภทที่ 2:

    นำเข้าส่วนหัว :#import "Reachability.h"

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

ขั้นตอนที่ 4:วิธีใช้:

- (void)CheckInternet
{
    BOOL network = [self currentNetworkStatus];
    if (network)
    {
        NSLog(@"Network Available");
    }
    else
    {
        NSLog(@"No Network Available");
    }
}

แบบอะซิงโครนัสชนิด 1 หรือไม่
Supertecnoboff

ฉันต้องการการแก้ไขประเภท 2 จากคำตอบของคุณ ฉันได้เพิ่มคลาสการเข้าถึงได้และฉันพยายามตรวจสอบการเชื่อมต่อโดยใช้คำตอบของคุณ มันสามารถเข้าถึงได้เสมอแม้ว่าฉันจะเชื่อมต่อกับ WiFi แต่ไม่มีการเชื่อมต่ออินเทอร์เน็ต WiFi ไม่ได้หมายความว่ามีการเชื่อมต่ออินเทอร์เน็ต ฉันต้องการตรวจสอบการเชื่อมต่ออินเทอร์เน็ตแม้จะมีการเชื่อมต่อ WiFi คุณช่วยฉันออกได้ไหม
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;
}
}

7
แม้ว่าอุปกรณ์นั้นจะเชื่อมต่อกับ Wifi หรือเครือข่ายอื่น ๆ แต่การเชื่อมต่ออินเทอร์เน็ตก็ยังไม่สามารถใช้งานได้ ทดสอบอย่างง่าย: เชื่อมต่อกับ wifi ที่บ้านแล้วถอดปลั๊กเคเบิลโมเด็ม ยังคงเชื่อมต่อกับ wifi แต่ไม่มีอินเทอร์เน็ต
iwasrobbed

11
- (void)viewWillAppear:(BOOL)animated
{
    NSString *URL = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com"]];

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

หรือใช้คลาสการเข้าถึงระดับ

มีสองวิธีในการตรวจสอบความพร้อมใช้งานอินเทอร์เน็ตโดยใช้ iPhone SDK:

1. ตรวจสอบว่าหน้า Google เปิดอยู่หรือไม่

2. ระดับการเข้าถึง

สำหรับข้อมูลเพิ่มเติมโปรดดูที่ความสามารถเข้าถึงได้ (นักพัฒนา Apple)


1
มีสองวิธีในการตรวจสอบความพร้อมใช้งานอินเทอร์เน็ตใน iPhone SDK 1) ตรวจสอบว่าหน้า Google เปิดอยู่หรือไม่
IOS Rocks

1
-1: นี่เป็นวิธีการซิงโครนัสที่จะบล็อกเธรดหลัก (อันที่ UI ของแอปเปลี่ยนไป) ในขณะที่มันพยายามเชื่อมต่อกับ google.com หากผู้ใช้ของคุณใช้การเชื่อมต่อข้อมูลที่ช้ามากโทรศัพท์จะทำหน้าที่เหมือนกระบวนการไม่ตอบสนอง
iwasrobbed


10

ก่อน : เพิ่มCFNetwork.frameworkในกรอบ

รหัส :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");
    }
}

8

แรกดาวน์โหลดระดับการเชื่อมและใส่ reachability.h และไฟล์ reachabilty.m ของคุณในXcode

วิธีที่ดีที่สุดคือการสร้างคลาสฟังก์ชั่นทั่วไป (NSObject) เพื่อให้คุณสามารถใช้คลาสใดก็ได้ นี่เป็นสองวิธีสำหรับการตรวจสอบการเชื่อมต่อเครือข่าย:

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

ตอนนี้คุณสามารถตรวจสอบการเชื่อมต่อเครือข่ายในชั้นเรียนใด ๆ โดยเรียกวิธีการเรียนนี้


8

นอกจากนี้ยังมีวิธีอื่นในการตรวจสอบการเชื่อมต่ออินเทอร์เน็ตโดยใช้ iPhone SDK

ลองใช้รหัสต่อไปนี้สำหรับการเชื่อมต่อเครือข่าย

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


8
  1. ดาวน์โหลดไฟล์ความสามารถเข้าถึงได้https://gist.github.com/darkseed/1182373

  2. และเพิ่มCFNetwork.frameworkและ 'SystemConfiguration.framework' ในกรอบ

  3. ทำ #import "Reachability.h"


ก่อน : เพิ่มCFNetwork.frameworkในกรอบ

รหัส :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");
    }
}

8

Swift 3 / Swift 4

คุณต้องนำเข้าก่อน

import SystemConfiguration

คุณสามารถตรวจสอบการเชื่อมต่ออินเทอร์เน็ตด้วยวิธีการดังต่อไปนี้

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)

}

7

ระดับ reachabilityตกลงเพื่อดูว่าการเชื่อมต่ออินเทอร์เน็ตที่สามารถใช้ได้กับอุปกรณ์หรือไม่ ...

แต่ในกรณีที่เข้าถึงทรัพยากรอินทราเน็ต :

การ Ping เซิร์ฟเวอร์อินทราเน็ตด้วยคลาสความสามารถในการเข้าถึงจะส่งคืนค่าจริง

ดังนั้นวิธีแก้ปัญหาอย่างรวดเร็วในสถานการณ์นี้คือการสร้างวิธีการทางเว็บที่เรียกว่าpingmeพร้อมกับวิธีการอื่น ๆ บนบริการ pingmeควรกลับบางสิ่งบางอย่าง

ดังนั้นฉันจึงเขียนวิธีต่อไปนี้ในฟังก์ชั่นทั่วไป

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

วิธีการข้างต้นมีประโยชน์มากสำหรับฉันดังนั้นเมื่อใดก็ตามที่ฉันพยายามส่งข้อมูลบางอย่างไปยังเซิร์ฟเวอร์ฉันจะตรวจสอบความสามารถในการเข้าถึงทรัพยากรอินทราเน็ตของฉันโดยใช้ URLRequest ที่มีการหมดเวลาต่ำ


7

เมื่อต้องการทำสิ่งนี้ด้วยตัวคุณเองนั้นง่ายมาก วิธีการต่อไปนี้จะใช้งานได้ เพียงให้แน่ใจว่าไม่อนุญาตให้ใช้ชื่อโฮสต์โปรโตคอลเช่น HTTP, HTTPS และอื่น ๆ ที่จะถูกส่งผ่านด้วยชื่อ

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

มันง่ายและรวดเร็วไม่เจ็บปวด


7

นอกเหนือจากการเชื่อมคุณยังอาจใช้ง่ายห้องสมุดผู้ช่วยปิง มันใช้งานได้ดีมากและง่ายต่อการรวมเข้าด้วยกัน


7

ฉันคิดว่าอันนี้เป็นคำตอบที่ดีที่สุด

"ใช่" หมายถึงการเชื่อมต่อ "ไม่" หมายถึงตัดการเชื่อมต่อ

#import "Reachability.h"

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

    if (internetStats == NotReachable)
    {
        return NO;
    }
    else
    {
        return YES;
    }
}

6

นำเข้าReachable.hคลาสในของคุณViewControllerและใช้รหัสต่อไปนี้เพื่อตรวจสอบการเชื่อมต่อ :

     #define hasInternetConnection [[Reachability reachabilityForInternetConnection] isReachable]
     if (hasInternetConnection){
           // To-do block
     }

คำตอบของคุณคือสิ่งที่ฉันกำลังค้นหา คุณควรได้รับการโหวตขึ้น xD
Nikel Arteta

ไม่ทำงานหากคุณเชื่อมต่อกับ WiFi โดยไม่ใช้อินเทอร์เน็ต
Keselme

6
  • ขั้นตอนที่ 1: เพิ่มคลาสการเข้าถึงในโครงการของคุณ
  • ขั้นตอนที่ 2: นำเข้าคลาสการเข้าถึง
  • ขั้นตอนที่ 3: สร้างฟังก์ชั่นด้านล่าง

    - (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;
            }
        }
    }
  • ขั้นตอนที่ 4: เรียกใช้ฟังก์ชันดังต่อไปนี้:

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

เอกสารของ Apple ระบุไว้นี้: ความสามารถในการเข้าถึงไม่สามารถบอกแอปพลิเคชันของคุณได้หากคุณสามารถเชื่อมต่อกับโฮสต์เฉพาะได้เฉพาะว่ามีอินเตอร์เฟสที่อาจอนุญาตการเชื่อมต่อหรือไม่และอินเตอร์เฟสนั้นเป็น WWAN หรือไม่
noobsmcgoobs
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.