iOS/iPhone Reachability - How to only check when internet is lost/not reachable using Reachability.m/.h

前端 未结 7 463
一生所求
一生所求 2021-02-01 09:59

Currently i am using the class by apple reachability.m/.h and it works, except it notifies me for any change, where as i would like to only notify the user if the network is not

7条回答
  •  无人及你
    2021-02-01 10:37

    We can check rechability using this code

    add class Reachability.h

    #import 
    #import 
    
    typedef enum {
    NotReachable = 0,
    ReachableViaWiFi,
    ReachableViaWWAN
    } NetworkStatus;
    #define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification"
    
    @interface Reachability: NSObject
    {
    BOOL localWiFiRef;
    SCNetworkReachabilityRef reachabilityRef;
    }
    
    //reachabilityWithHostName- Use to check the reachability of a particular host name. 
    + (Reachability*) reachabilityWithHostName: (NSString*) hostName;
    
    //reachabilityWithAddress- Use to check the reachability of a particular IP address. 
    + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
    
    //reachabilityForInternetConnection- checks whether the default route is available.  
    //  Should be used by applications that do not connect to a particular host
    + (Reachability*) reachabilityForInternetConnection;
    
    //reachabilityForLocalWiFi- checks whether a local wifi connection is available.
    + (Reachability*) reachabilityForLocalWiFi;
    
    //Start listening for reachability notifications on the current run loop
    - (BOOL) startNotifier;
    - (void) stopNotifier;
    
    - (NetworkStatus) currentReachabilityStatus;
    //WWAN may be available, but not active until a connection has been established.
    //WiFi may require a connection for VPN on Demand.
    - (BOOL) connectionRequired;
     @end
    

    Reachability.m

    #import 
                #import 
                #import 
                #import 
                #import 
                #import 
    
                #import 
    
                #import "Reachability.h"
    
                #define kShouldPrintReachabilityFlags 1
    
                static void PrintReachabilityFlags(SCNetworkReachabilityFlags    flags, const char* comment)
                {
                #if kShouldPrintReachabilityFlags
    
                    NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
                            (flags & kSCNetworkReachabilityFlagsIsWWAN)               ? 'W' : '-',
                            (flags & kSCNetworkReachabilityFlagsReachable)            ? 'R' : '-',
    
                            (flags & kSCNetworkReachabilityFlagsTransientConnection)  ? 't' : '-',
                            (flags & kSCNetworkReachabilityFlagsConnectionRequired)   ? 'c' : '-',
                            (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic)  ? 'C' : '-',
                            (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
                            (flags & kSCNetworkReachabilityFlagsConnectionOnDemand)   ? 'D' : '-',
                            (flags & kSCNetworkReachabilityFlagsIsLocalAddress)       ? 'l' : '-',
                            (flags & kSCNetworkReachabilityFlagsIsDirect)             ? 'd' : '-',
                            comment
                            );
                #endif
                }
    
    
                @implementation Reachability
                static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
                {
                    #pragma unused (target, flags)
                    NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
                    NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
    
                    //We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively
                    // in case someon uses the Reachablity object in a different thread.
                    NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init];
    
                    Reachability* noteObject = (Reachability*) info;
                    // Post a notification to notify the client that the network reachability changed.
                    [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
    
                    [myPool release];
                }
    
                - (BOOL) startNotifier
                {
                    BOOL retVal = NO;
                    SCNetworkReachabilityContext    context = {0, self, NULL, NULL, NULL};
                    if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
                    {
                        if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
                        {
                            retVal = YES;
                        }
                    }
                    return retVal;
                }
    
                - (void) stopNotifier
                {
                    if(reachabilityRef!= NULL)
                    {
                        SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
                    }
                }
    
                - (void) dealloc
                {
                    [self stopNotifier];
                    if(reachabilityRef!= NULL)
                    {
                        CFRelease(reachabilityRef);
                    }
                    [super dealloc];
                }
    
                + (Reachability*) reachabilityWithHostName: (NSString*) hostName;
                {
                    Reachability* retVal = NULL;
                    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
                    if(reachability!= NULL)
                    {
                        retVal= [[[self alloc] init] autorelease];
                        if(retVal!= NULL)
                        {
                            retVal->reachabilityRef = reachability;
                            retVal->localWiFiRef = NO;
                        }
                    }
                    return retVal;
                }
    
                + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
                {
                    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
                    Reachability* retVal = NULL;
                    if(reachability!= NULL)
                    {
                        retVal= [[[self alloc] init] autorelease];
                        if(retVal!= NULL)
                        {
                            retVal->reachabilityRef = reachability;
                            retVal->localWiFiRef = NO;
                        }
                    }
                    return retVal;
                }
    
                + (Reachability*) reachabilityForInternetConnection;
                {
                    struct sockaddr_in zeroAddress;
                    bzero(&zeroAddress, sizeof(zeroAddress));
                    zeroAddress.sin_len = sizeof(zeroAddress);
                    zeroAddress.sin_family = AF_INET;
                    return [self reachabilityWithAddress: &zeroAddress];
                }
    
                + (Reachability*) reachabilityForLocalWiFi;
                {
                    struct sockaddr_in localWifiAddress;
                    bzero(&localWifiAddress, sizeof(localWifiAddress));
                    localWifiAddress.sin_len = sizeof(localWifiAddress);
                    localWifiAddress.sin_family = AF_INET;
                    // IN_LINKLOCALNETNUM is defined in  as 169.254.0.0
                    localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
                    Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress];
                    if(retVal!= NULL)
                    {
                        retVal->localWiFiRef = YES;
                    }
                    return retVal;
                }
    
                #pragma mark Network Flag Handling
    
                - (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags
                {
                    PrintReachabilityFlags(flags, "localWiFiStatusForFlags");
    
                    BOOL retVal = NotReachable;
                    if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
                    {
                        retVal = ReachableViaWiFi;  
                    }
                    return retVal;
                }
    
                - (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags
                {
                    PrintReachabilityFlags(flags, "networkStatusForFlags");
                    if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
                    {
                        // if target host is not reachable
                        return NotReachable;
                    }
    
                    BOOL retVal = NotReachable;
    
                    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
                        retVal = ReachableViaWiFi;
                    }
    
    
                    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
                                retVal = ReachableViaWiFi;
                            }
                        }
    
                    if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
                    {
                        // ... but WWAN connections are OK if the calling application
                        //     is using the CFNetwork (CFSocketStream?) APIs.
                        retVal = ReachableViaWWAN;
                    }
                    return retVal;
                }
    
                - (BOOL) connectionRequired;
                {
                    NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
                    SCNetworkReachabilityFlags flags;
                    if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
                    {
                        return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
                    }
                    return NO;
                }
    
                - (NetworkStatus) currentReachabilityStatus
                {
                    NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef");
                    NetworkStatus retVal = NotReachable;
                    SCNetworkReachabilityFlags flags;
                    if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
                    {
                        if(localWiFiRef)
                        {
                            retVal = [self localWiFiStatusForFlags: flags];
                        }
                        else
                        {
                            retVal = [self networkStatusForFlags: flags];
                        }
                    }
                    return retVal;
                }
                @end
    

    and use via direct calling method in appdel class using

      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
    
    
    
     -(void) checkNetworkStatus:(NSNotification *)notice
    {
    
     Reachability* internetReachable;
      BOOL isInternetActive;
    // called after network status changes
    NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
    switch (internetStatus)
    {
        case NotReachable:
        {
            NSLog(@"The internet is down.");
            isInternetActive = NO;
    
            break;
        }
        case ReachableViaWiFi:
        {
            NSLog(@"The internet is working via WIFI.");
            isInternetActive = YES;
    
            break;
        }
        case ReachableViaWWAN:
        {
            NSLog(@"The internet is working via WWAN.");
            isInternetActive = 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;
        }
     }
    }
    

提交回复
热议问题