Como verificar o Wi-Fi local (não apenas a conexão celular) usando o iPhone SDK?

No momento, estou usando o seguinte para verificar se o Wi-Fi está disponível para meu aplicativo:

#import  static inline BOOL addressReachable(const struct sockaddr_in *hostAddress); BOOL localWiFiAvailable() { 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); return addressReachable(&localWifiAddress); } static inline BOOL addressReachable(const struct sockaddr_in *hostAddress) { const SCNetworkReachabilityRef target = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress); if (target != NULL) { SCNetworkReachabilityFlags flags = 0; const BOOL reachable = SCNetworkReachabilityGetFlags(target, &flags); CFRelease(target); return reachable && (flags & kSCNetworkFlagsReachable); } return NO; } 

Isso, no entanto, não retorna NÃO como deveria quando o iPhone está conectado apenas a uma rede celular, mas não a uma rede Wi-Fi. Alguém sabe como consertar isso?

Editar

Então foi isso que acabei usando:

 #import  // For AF_INET, etc. #import  // For getifaddrs() #import  // For IFF_LOOPBACK BOOL localWiFiAvailable() { struct ifaddrs *addresses; struct ifaddrs *cursor; BOOL wiFiAvailable = NO; if (getifaddrs(&addresses) != 0) return NO; cursor = addresses; while (cursor != NULL) { if (cursor -> ifa_addr -> sa_family == AF_INET && !(cursor -> ifa_flags & IFF_LOOPBACK)) // Ignore the loopback address { // Check for WiFi adapter if (strcmp(cursor -> ifa_name, "en0") == 0) { wiFiAvailable = YES; break; } } cursor = cursor -> ifa_next; } freeifaddrs(addresses); return wiFiAvailable; } 

Obrigado “unforgiven” (e Matt Brown, aparentemente).

Primeiro, modifique seu método addressReachable. Ao invés de

 return reachable && (flags & kSCNetworkFlagsReachable); 

adicione o seguinte:

 BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0); BOOL needsConnection = ((flags & kSCNetworkFlagsConnectionRequired) != 0); return (isReachable && !needsConnection) ? YES : NO; 

Essa é a maneira correta de verificar se há uma conexão disponível. Agora, se você quiser distinguir claramente entre celular e wifi, modifique seu método para retornar um int e use o seguinte

 BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0); BOOL needsConnection = ((flags & kSCNetworkFlagsConnectionRequired) != 0); if(isReachable && !needsConnection) // connection is available { // determine what type of connection is available BOOL isCellularConnection = ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0); NSString *wifiIPAddress = [self getWiFiIPAddress]; if(isCellularConnection) return 1; // cellular connection available if(wifiIPAddress) return 2; // wifi connection available } else return 0; // no connection at all 

O método getWiFiIPAddress é cortesia de Matt Brown e pode ser encontrado aqui .

Mais uma coisa. O sinalizador kSCNetworkReachabilityFlagsIsDirect pode informar se o tráfego de rede passa por um gateway ou chega diretamente. Isso pode ser útil em alguns casos.

O código funciona corretamente no dispositivo. No simulador, ele irá declarar que você está conectado através de wifi quando você está conectado através do cabo ethernet, e não declarará nenhuma conexão se você estiver conectado através de wifi.

Veja este link: http://developer.apple.com/iphone/library/samplecode/Reachability/

Você precisa estar registrado desenvolvedor para baixar o exemplo de código. Também e é importante! A API de acessibilidade funciona para 3.0 ou mais SDKs, mas falha para versões inferiores.

BTW, pelo novo HIG, todas as aplicações que dependem da conexão WiFi precisam alertar o usuário sobre sua ausência, ou seja, se o dispositivo não estiver conectado ao Wifi, informe o usuário.

Versão rápida

 import Foundation import SystemConfiguration public class Reachability { class func isInternetAvailable() -> Bool { let IPaddress = "google.com"//WebServicesUtil.sharedInstance.getHostIPAddress() if let host_name = IPaddress.cStringUsingEncoding(NSASCIIStringEncoding) { let reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, host_name).takeRetainedValue() var flags: SCNetworkReachabilityFlags = 0 if SCNetworkReachabilityGetFlags(reachability, &flags) == 0 { return false } let isReachable = (flags & UInt32(kSCNetworkFlagsReachable)) != 0 let needsConnection = (flags & UInt32(kSCNetworkFlagsConnectionRequired)) != 0 return (isReachable && !needsConnection) } else { return false } } } 

Confira a class de acessibilidade fornecida pela Apple. Isso permite que você verifique qual conectividade o dispositivo possui atualmente, entre Wifi, celular ou nenhum. Você pode até registrar notifications quando a conectividade mudar.

Infelizmente, o Google é para mim no momento, mas pesquisando “alcance do iPhone” você vai ter o que você precisa.

 -(Bool)isDataSourceAvailableNow { BOOL isDataSourceAvailable; bool success = false; const char *host_name = [@"www.google.com" cStringUsingEncoding:NSASCIIStringEncoding]; SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, host_name); if (reachability) { SCNetworkReachabilityFlags flags; success = SCNetworkReachabilityGetFlags(reachability, &flags); isDataSourceAvailable = success && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired); CFRelease(reachability); } return isDataSourceAvailable; }