Search code examples
iosswiftswift3nsunknownkeyexceptionanyobject

Key value coding compliancy error on IBAction


Disclaimer: Ignore the fact that a production app using this may or may not pass review. I'm just trying to get this concept to work. Here's the code I'm trying to execute, all I'm trying to do (for now) is initialize four constants and it has difficulty on the third.

let app = UIApplication.shared
let statusBar = app.value(forKey: "statusBar") as AnyObject
let foregroundView = statusBar.value(forKey: "foregroundView") as AnyObject
let subviews = Array(foregroundView.subviews)

The error is given:

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<_SwiftValue 0x170087850> valueForUndefinedKey:]: this class is not key value coding-compliant for the key foregroundView.'

Note that, unlike most other key value compliancy error that occur when the app is ran, mine only occurs when executing the IBAction (triggered by UIButton) that has the four line of code in it.

For reference, I'm trying to achieve what this post describes in Objective-C. I'm new to Swift but I think I translated it properly.

The entire func is here:

@IBAction func getSignal(_ sender: UIButton) {

    let app = UIApplication.shared
    let statusBar = app.value(forKey: "statusBar") as AnyObject
    let foregroundView = statusBar.value(forKey: "foregroundView") as AnyObject
    let subviews = Array(foregroundView.subviews)
    var dataNetworkItemView: UIView?
    for subview in subviews {
        if (subview as AnyObject).isKind(of: NSClassFromString("UIStatusBarSignalStrengthItemView")!) {
            dataNetworkItemView = subview
            break
        }
    }
    let signalStrength = (dataNetworkItemView?.value(forKey: "signalStrengthRaw") as? NSString)?.intValue
    print("signal \(signalStrength)")
}

which I converted from the block of original code, here:

    UIApplication *app = [UIApplication sharedApplication];
    NSArray *subviews = [[[app valueForKey:@"statusBar"]     valueForKey:@"foregroundView"] subviews];
    NSString *dataNetworkItemView = nil;
    for (id subview in subviews) {
        if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarSignalStrengthItemView") class]])
        {
            dataNetworkItemView = subview;
            break;
        }
    }
    int signalStrength = [[dataNetworkItemView valueForKey:@"signalStrengthRaw"] intValue];
    NSLog(@"signal %d", signalStrength);

There are no compile-time errors or warnings, and I'm at a loss for how to continue. Thanks.


Solution

  • Working Xcode 8 beta, Swift 3.0 Code:

    let app = UIApplication.shared
    let statusBar = app().value(forKey: "statusBar")! as AnyObject
    let foregroundView = statusBar.value(forKey: "foregroundView")! as AnyObject
    let subviews = Array(foregroundView.subviews)
    var dataNetworkItemView: UIView?
    for subview in subviews {
        if (subview as AnyObject).isKind(of: NSClassFromString("UIStatusBarSignalStrengthItemView")!) {
            dataNetworkItemView = subview
            break
        }
    }
    let signalStrength = (dataNetworkItemView?.value(forKey: "signalStrengthRaw") as? NSString)?.intValue
    print("signal \(signalStrength)")
    

    The OP is using Xcode 8 GM, hence one change- app() to app:

    let statusBar = app.value(forKey: "statusBar")! as AnyObject