WillB WillB - 2 months ago 74
Swift Question

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.

Answer

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