Adrian Adrian - 1 month ago 10
iOS Question

Difficulty reading UserDefaults with Fastlane Snapshot

I'm using Fastlane's

to create screenshots for an app I'm about to submit to the App Store.

It works "as advertised" for the most part, but it doesn't seem to like the way I access the
UserDefaults
within my app. On one test, it generates an Exit status: 65 error.

UI Testing Failure - com.me.MyApp crashed in (extension in MyApp):__ObjC.NSObject.defaultTime () -> Swift.Float


I find
UserDefaults.standard.value(forKey: "defaultTime")
to an invitation for a syntax error, so I created an extension to access
UserDefaults
. Here's what the extension looks like:

class CustomExtensions: NSObject {
/*
This is blank. Nothing else in here. No really...nothing else
*/
}

extension NSObject {
// User Defaults
func defaultTime() -> Float {
return UserDefaults.standard.value(forKey: "defaultTime") as! Float
}

// a bunch of other UserDefaults
}


Wihin the app, whenever I need
defaultTime
, I just type
defaultTime()
. Using this method to access
UserDefaults
values works fine in the Simulator and on the devices I've tested. I only encounter a problem with
snapshot
.

I've tried adding in
sleep(1)
within the test, but that doesn't seem to do anything. I welcome suggestions re: alternative means of accessing
UserDefaults
that enable me to access them easily throughout MyApp.

Answer

What's probably happening is that, in your simulator and on device, you're writing a value to user defaults for the key defaultTime before it is ever read. value(forKey: returns an optional, and if you force-unwrap it (or force down-cast as your are doing here), you will crash if the value is nil. Try either returning an optional:

func defaultTime() -> Float? {
    return UserDefaults.standard.value(forKey: "defaultTime") as? Float
}

or using a default value:

func defaultTime() -> Float {
    return UserDefaults.standard.value(forKey: "defaultTime") as? Float ?? 0.0
}