skip to Main Content

I want to get the device Wi-Fi strength, but found no straightforward way to accomplish this

Right now I have this which used to work before iOS 13 however now I get this crash.

func wifiStrength() -> Double {
    let app = UIApplication.shared
    let subviews = ((app.value(forKey: "statusBar") as! NSObject).value(forKey: "foregroundView") as! UIView).subviews
    var dataNetworkItemView: UIView?

    for subview in subviews {
        if subview.isKind(of: NSClassFromString("UIStatusBarDataNetworkItemView")!) {
            dataNetworkItemView = subview
            break
        }
    }

    let dBm = (dataNetworkItemView!.value(forKey: "wifiStrengthRaw") as! NSNumber).intValue
    var strength = (Double(dBm) + 90.0) / 60.0
    if strength > 1 {
        strength = 1
    }
    return strength
}

The crash error message.

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'App called -statusBar or -statusBarWindow on UIApplication: this code must be changed as there's no longer a status bar or status bar window. Use the statusBarManager object on the window scene instead.'

terminating with uncaught exception of type NSException

Does anyone know how to adapt the previous approach on iOS 13?
Or of a different way to gather Wi-Fi signal strength.

2

Answers


  1. Chosen as BEST ANSWER

    I solve the problem this is the updated code which works on iOS 15

        func wifiStrength() -> Double {
            let statusBarManager = UIApplication.shared
                .keyWindow?
                .windowScene?
                .statusBarManager
            let hascreateLocalStatusBar = statusBarManager?
                .responds(to: Selector("createLocalStatusBar"))
            
            if !(hascreateLocalStatusBar ?? false) {
                return -1
            }
            
            guard let createLocalStatusBar = statusBarManager?
                .perform(Selector("createLocalStatusBar"))
                .takeUnretainedValue() as?
                UIView else { print("not UIVirw"); return -1};
    
            let hasStatusBar = createLocalStatusBar.responds(to:  Selector("statusBar"))
            if !hasStatusBar {
                return -1
            }
            
            let statusBar = (createLocalStatusBar.perform(Selector("statusBar"))
                .takeUnretainedValue() as! UIView)
                
        
            guard let value = (((statusBar.value(forKey: "_statusBar") as? NSObject)?
                .value(forKey: "_currentAggregatedData") as? NSObject)?
                .value(forKey: "_wifiEntry") as? NSObject)?
                .value(forKey: "_rawValue") else { return -1}
                    
            print("🌶(value)")
            let dBm = value as! Int
            var strength = (Double(dBm) + 90.0) / 60.0
                    
            if strength > 1 {
                strength = 1
            }
            return strength
        }
    
    

    In regards to AppStore legality, I am aware that this practice is not allowed by apple, and want to clarify that I'm not planning to use this in any production code just for pure experimentation sake.


  2. There is no way to get wifi strength on an iOS application. Please see this thread in Apple Developer Forums: https://developer.apple.com/forums/thread/107046?answerId=325726022#325726022

    there is no supported way for general apps to get Wi-Fi signal strength on iOS

    Rooting around internal / private structures using value(forKey:) is unsupported, unstable, and could get your app rejected from the app store.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search