iOS Reachability SCNetworkReachabilitySetCallback не перезванивать при переключении формы Wi-Fi на Anthor Wi-Fi - PullRequest
0 голосов
/ 14 мая 2018

Я хочу получить звонок, когда сеть переходит на iPhone.

Я использую руководство Reachability.m от Apple следующим образом:

xxx.m

struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
Reachability = [self reachabilityWithAddress: (const struct sockaddr *) &zeroAddress]

Reachability.m

BOOL returnValue = NO;
SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context))
{
    if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetMain(), kCFRunLoopDefaultMode))
    {
        returnValue = YES;
    }
}
return returnValue;

xxx.m

ReachabilityCallback {
    //do something when network change
}

Я тестирую смену мобильного телефона (4G) на wifi1

, получает вызов как

Status4G
StatusNone
StatusWifi1

При изменении формы wifi1 на wifi2

StatusWifi1
StatusNone
StatusWifi2

Однако иногда, когда wifi меняется очень быстро и не меняется на StatusNone, я не получаю обратный вызов, когда я меняю wifi1 на wifi2 или наоборот,

Что я хочу получить, это

StatusWifi1
StatusWifi2

-------------------------UPDATE----------------------------

Спасибо @Hitesh Surani, теперь мой вопрос иногда возникает на некоторых устройствах, я не получил disconnect state, Я пытаюсь использовать

[self reachabilityWithAddress: @"www.google.com"]

Заменить

[self reachabilityWithAddress: (const struct sockaddr *) &zeroAddress]

Теперь я могу получить обратный вызов, когда Wi-Fi меняется, даже если он не превратился в disconnect state, но я все еще не сделалИзвестно почему, вот изменение состояния:

//wifi1:
1 kSCNetworkReachabilityFlagsReachable

//wifi1 -> wifi2
2 kSCNetworkReachabilityFlagsReachable | kSCNetworkReachabilityFlagsTransientConnection
3 kSCNetworkReachabilityFlagsReachable

при изменении wifi существует состояние tmp kSCNetworkReachabilityFlagsReachable | kSCNetworkReachabilityFlagsTransientConnection, поэтому я могу обнаружить изменения wifi, но что означает kSCNetworkReachabilityFlagsTransientConnection?Я читаю документацию Apple, все еще в замешательстве.

1 Ответ

0 голосов
/ 14 мая 2018

Спасибо, что задали большой вопрос.

В основном Reachability класс используется для отслеживания изменений интернет-соединения. Там нет провенса для обнаружения уведомлений об изменении Wi-Fi. Так что одним словом Reachability класс не предоставит такой функциональности. Если вы хотите выполнить ваши требования, то ниже настройки требуется.

Вы можете получить уведомление об изменении wifi, как показано ниже.

  • Когда ваше Wi-Fi-соединение изменилось или вы переключились на любую другую сеть, вы получили состояние отключения на долю секунды. Итак, reachabilityChanged метод называется.

  • Используя приведенный ниже код, вы можете получить информацию о Wi-Fi, такую ​​как BSSID, SSID (имя) и данные SSID. Просто храните информацию о Wi-Fi в местном.

  • Когда сеть изменилась, вы можете проверить, соответствует ли новая информация Wi-Fi предыдущим или нет. Если нет, то пользователь подключается с новым Wi-Fi.

Введите следующий код в метод reachabilityChanged.

import SystemConfiguration.CaptiveNetwork

 func printCurrentWifiInfo() {
            if let interface = CNCopySupportedInterfaces() {
                for i in 0..<CFArrayGetCount(interface) {
                    let interfaceName: UnsafeRawPointer = CFArrayGetValueAtIndex(interface, i)
                    let rec = unsafeBitCast(interfaceName, to: AnyObject.self)
                    if let unsafeInterfaceData = CNCopyCurrentNetworkInfo("\(rec)" as CFString), let interfaceData = unsafeInterfaceData as? [String : AnyObject] {
                        // connected wifi
                        print("BSSID: \(String(describing: interfaceData["BSSID"])), SSID: \(String(describing: interfaceData["SSID"])), SSIDDATA: \(String(describing: interfaceData["SSIDDATA"]))")
                    } else {
                        //Wifi is not connected
                    }
                }
            }
        }

Обновление:

Apple предоставляет com.apple.system.config.network_change для прослушивания уведомлений об изменениях wifi. В основном это часть Core Foundation Framework. Я уверен, что это будет работать для вас.

Пожалуйста, добавьте ниже код для прослушивания изменений Wi-Fi.

 let notificationName = "com.apple.system.config.network_change"


    func onNetworkChange(_ name : String) {
        if (name == notificationName) {
            // Do your stuff
            print("Network was changed")
        }
    }

    func registerObserver() {
        let observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())
        CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), observer,
                                        { (nc, observer, name, _, _) -> Swift.Void in
                                            if let observer = observer, let name = name {
                                                let instance = Unmanaged<Reachability>.fromOpaque(observer).takeUnretainedValue()
                                                instance.onNetworkChange(name.rawValue as String)
                                            } },
                                        notificationName as CFString, nil, .deliverImmediately)
    }


    func removeObserver() {
        let observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())
        CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), observer, nil, nil)
    }

Зарегистрировать наблюдателя в init и удалить в deinit. Найти ссылку из Здесь .

...