[ios] iOS에서 인터넷 연결을 감지하는 가장 쉬운 방법은 무엇입니까?
나는이 질문이 다른 많은 사람들의 속임수 인 것처럼 보이지만 간단한 사례가 여기에 잘 설명되어 있다고 생각하지 않습니다. HTTPUrlConnection
사용 가능한 연결이없는 경우 Android 및 BlackBerry 배경에서 가져와 요청을 즉시 실패하게합니다. 이것은 완전히 제정신의 행동처럼 보이고, NSURLConnection
iOS에서 그것을 모방하지 않았다는 사실에 놀랐 습니다.
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를 켜거나 끄면 시뮬레이터가 전화 설정을 무시합니다.
최신 정보:
-
결국 메인 스레드를 차단하지 않기 위해 스레드 / 비동기 콜백을 사용했습니다. 정기적으로 다시 테스트하여 캐시 된 결과를 사용할 수 있습니다. 데이터 연결을 불필요하게 열어 두지 않아야합니다.
-
@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;
}