Pat Needham
Pat Needham

Reputation: 5638

Accessing NSProcessInfo.processInfo().environment in AppDelegate causing crash only when opening iOS app outside of Xcode

I have an iOS app built with Swift 2.2 and started having a problem recently. It works fine when building and running via Xcode, but after stopping the app from Xcode and then trying to open it again directly from the phone (both real device and simulator), it crashes before loading the initial view controller.

I was able to symbolicate the crash logs and the first line inside Thread 0 Crashed contains:

0x001aa754 specialized AppDelegate.application(UIApplication, didFinishLaunchingWithOptions : [NSObject : AnyObject]?) -> Bool (AppDelegate.swift:417)

On the line inside AppDelegate I have:

let buildFor = NSProcessInfo.processInfo().environment["BUILD_FOR"]! as String

I confirmed that was the cause of the crash because after commenting out that line and replacing it with let buildFor = "DEV" I was able to open the app from the home screen without any problem after closing it in Xcode.

I have two schemes, one where the BUILD_FOR environment variable is DEV and the other where it is PROD. What causes that value to be present when running via Xcode but not from the device/simulator, and how can I change that? That environment variable is used in multiple places (primarily in AppDelegate) to determine which URLs to use, either for production or development server, as well as using appropriate API keys for third-party services. I would like to have it set to DEV for the TestFlight build and PROD for when it's in the App Store.

Upvotes: 1

Views: 2786

Answers (1)

Pat Needham
Pat Needham

Reputation: 5638

I eventually went with another approach instead of using NSProcessInfo.processInfo(). Under Targets -> Build Settings -> Other Swift Flags, I went with two different flags, DEBUG and RELEASE like this: enter image description here

Then within AppDelegate.swift I use the Swift preprocessor macros #if/#else/#end to define my original buildFor boolean variable:

#if DEBUG
    let buildFor = "DEV"
    print("it is DEV")
#else
    let buildFor = "PROD"
    print("it is PROD")
#endif

// setting appropriate API keys, server URLs, etc
let apiKey = buildFor == "DEV" ? "testing api key" : "production one"

Doing it this way doesn't require multiple Xcode schemes.

Upvotes: 1

Related Questions