2011-01-23 2 views
10

을 사용하여 인터넷이 끊어 졌거나 연결할 수없는 경우에만 확인하는 방법 현재 Apple reachability.m/.h로 수업을 사용하고 있습니다. 변경, 어디 네트워크에 연결할 수없는 경우 사용자에게 알리고 싶습니다. 현재 인터넷에 연결되어 있고 네트워크가 느슨한 경우 현재 알려줍니다. 그러나 네트워크에 다시 연결하면 나에게도 알려주므로 원하지 않습니다. 손실/네트워크가없는 경우에만 알려주고 싶습니다.iOS/iPhone Reachability - Reachability.m/.h

- (void)viewWillAppear:(BOOL)animated 
{ 
    // check for internet connection 
    [[NSNotificationCenter defaultCenter] 
      addObserver:self 
      selector:@selector(checkNetworkStatus:) 
       name:kReachabilityChangedNotification 
       object:nil]; 

    internetReachable = [[Reachability 
         reachabilityForInternetConnection] retain]; 
    [internetReachable startNotifier]; 

    // check if a pathway to a random host exists 
    hostReachable = [[Reachability reachabilityWithHostName: 
        @"www.google.ca"] retain]; 
    [hostReachable startNotifier]; 

    // now patiently wait for the notification 
} 

-[NSNotificationCenter addObserver:selector:name:object:]를 호출, 이름이 다음 다른 기능을 그대로 이름 인이 않습니다

나는 그것이 호출 할 수있는 뭔가가 생각? 이것은 NSNotificationCenter를 사용하는 나의 처음이므로이 문제에 정통하지 않습니다.

편집 : 내 checkNetworkStatus 기능이

여기

을한다 : (i가 무엇입니까 문제가있다 "NotReachable"네트워크 연결이 다시오고 및 NSAlert이 꺼집니다로 여러 번)

- (void) checkNetworkStatus:(NSNotification *)notice 
{ 
     // called after network status changes 
NetworkStatus internetStatus = [internetReachable currentReachabilityStatus]; 
switch (internetStatus) 

{ 
    case NotReachable: 
    { 
     UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Network Failed" message:@"Please check your connection and try again." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil ]; 
     [alert show]; 
     NSLog(@"The internet is down."); 

     break; 

    } 
    case ReachableViaWiFi: 
    {    
     NSLog(@"The internet is working via WIFI."); 

     break; 

    } 
    case ReachableViaWWAN: 
    { 
     NSLog(@"The internet is working via WWAN."); 

     break; 

    } 
} 

NetworkStatus hostStatus = [hostReachable currentReachabilityStatus]; 
switch (hostStatus) 

{ 
    case NotReachable: 
    { 
     NSLog(@"A gateway to the host server is down."); 

     break; 

    } 
    case ReachableViaWiFi: 
    { 
     NSLog(@"A gateway to the host server is working via WIFI."); 

     break; 

    } 
    case ReachableViaWWAN: 
    { 
     NSLog(@"A gateway to the host server is working via WWAN."); 

     break; 

    } 
} 

}

+0

재미있는 것 : 나는 아이폰이 AdHoc WiFi (인터넷 연결 없음)에 연결되어 있다면 결과가 여전히 WiFi를 통한 인터넷 연결에 긍정적이라는 것을 알아 챘다. –

+0

@rokjarc 그래서 호스트에 연결할 수 있는지 확인해야합니다. – Joe

+0

사실 : 사실 그것은 보통 당신이 알아야 할 전부입니다. 나는 단지 그 명명법이 틀렸다는 것을 믿는다 : 고립 된 AdHoc 네트워크에서 인터넷 (또는 WWW)은 접근 가능하지 않다. 그러나 나는 여기서 머리카락을 나눌 것이다. :) –

답변

5

도달 가능성은 상태가 변경되면 알림을 보내지 만 해당 알림으로하는 일은 전적으로 사용자가 결정합니다. 사용자에게 네트워크가 돌아 갔음을 알리고 싶지 않은 경우에는 필요하지 않습니다.

NSNotificationCenter 메서드의 "name"매개 변수는 구독중인 알림을 나타냅니다. 개체가 알림을 게시하면 특정 이름으로 알림을 보냅니다.

+0

내 편집을 보아라 – Mausimo

0

Reachability 클래스 전체를 구현하고 필요에 따라 코드에 연결하고 도달 가능성 부분을 제거하거나 주석 처리합니다. 알림을 받고 싶지 않은 것을 하나씩 제거하십시오. 분명히 obj-c, Reachability 클래스, 알림 등을 잘 이해해야하지만 그렇게 할 수 있습니다.

+0

내 편집을 보아라 – Mausimo

+0

AlertView가 표시 중이다 checkNetworkStatus가 여러 번 연속해서 호출되기 때문에 여러 번. 해당 메소드에 대한 다른 호출을 찾아 제거해야합니다. –

+0

나는 NSNotificationCenter에 한 번만 checkNetworkStatus를 두는 것을 이해하지 못한다 ... – Mausimo

1

나는 Reachability로 놀기 시작했고, 내가 발견 한 것이 당신에게 유용하다는 것을 알았습니다.

다시 연결할 때 '연결할 수 없음'과 관련하여 this에 연결할 수 있습니까? 여기서 포스터는 원격 호스트에 대해 '접근 가능'이라는 정의를 내놓았습니다. 패키지를 다시 연결하면 성공적으로 통과 할 수없는 것 같아요?

또 다른 가능성은 중요

도달 가능성있는 Readme.txt에 있습니다 도달 가능성은 해당 호스트의 도달 가능성을 결정하기 전에 호스트 이름을 해결하기 위해 DNS를 사용해야하며,이 특정 네트워크 연결에 시간이 걸릴 수 있습니다. 이 때문에 API는 이름 확인이 완료 될 때까지 NotReachable을 반환합니다. 이 지연은 일부 네트워크의 인터페이스에 표시되는 일 수 있습니다.

IP를 직접주고 도움이되는지 확인하십시오.

0

당신이 할 수있는 한 가지는 당신이 콜백에서 하나를 처리하는 동안 변경된 알림 NSNotificationCenter removeObserver ...를 탈퇴하는 것입니다. 돌아 오기 전에 관찰자를 다시 추가하십시오.

1

도달 가능성 2.2, 당신은이 문제를 해결하기 위해

[internetReachable startNotifier]; 

전에

[hostReach connectionRequired]; 

를 추가 할 수 있습니다.

runmad

여기에이 문제를 대답 : 당신은 단지 IP 주소로 www.hostname.com를 교체하는 경우, 그것은 단지 한 번 대신 여러 번 경고합니다 https://stackoverflow.com/a/2157858/623260

0

우리는 Reachability.m

#import <sys/socket.h> 
      #import <netinet/in.h> 
      #import <netinet6/in6.h> 
      #import <arpa/inet.h> 
      #import <ifaddrs.h> 
      #import <netdb.h> 

      #import <CoreFoundation/CoreFoundation.h> 

      #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 <netinet/in.h> 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 

를이 코드

추가 클래스 Reachability.h

#import <Foundation/Foundation.h> 
#import <SystemConfiguration/SystemConfiguration.h> 

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 

를 사용하여 rechability을 확인하고 사용 appdel 클래스에서 직접 호출하는 방법을 통해 사용할 수 있습니다

[[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; 
    } 
} 
} 
+0

SCNetworkReachabilitySetCallback은 콜백이 연결이 끊어지기 바로 전에 시간이 경과 될 때까지 이루어지지 않은 iOS 8에서 이제는 다른 동작을합니다. – cynistersix

관련 문제