So, my App (iOS, Swift 2.2, Xcode 7.3) got rejected by Beta App Review team because it crahsed on launch.
UPDATE Got an answer from the App Review Team
Haha,
--@RJE... it was your comment that made me double check if I was forcefully unwrapping an optional. If you want the bounty, post an answer and I'll assign it to you! Thanks! – guido 5 hours ago"--
Bounties are always important,
Anyway it is very important to know that what is SIGTRAP means. It is basically a run-time exception not an error. So if you cannot really find the issue you have to check that if there are any places which can course an exception. (specially with Swift optional types)
Usually it can be array index out of bound or unwrapping nil or any thing similar. Also if it only occurs sometimes or only on some device there is a possibility of a issue due to various delays of UI animations.(e.g. presentViewController withAnimation and trying some thing before its completion.)
But honestly I don't see any issue with your original code. It shouldn't have crashed.
Unless if Storyboard's initial point is a UINavigationController and you forgot to set its class as a CustomNavigationController. Then it will crash at below code. (this is expected in Swift).
let navController = window!.rootViewController as! CustomNavigationController
But I don't think that this is the issue. Coz it should have crashed every time on any device.
And also by the time applicationDidBecomeActive called window wont be nil. So it can be some thing else you are doing with navController after this point.
Or may be Apple's review team tested your app on a faulty device :)
I got it approved.
UPDATE
While I got it approved, the next build of the app was rejected again, same reason, same sort of crash reports, again pointing to the first line of the viewDidLoad method.
I then radically threw all my code from viewDidLoad into viewWillAppear like this:
var viewLoaded = false
override func viewDidLoad() {
super.viewDidLoad()
// Do nothing
}
override func viewWillAppear(animated: Bool) {
if !viewLoaded {
// viewDidLoad code
viewLoaded = true
}
// viewWillAppear code
}
My theory now is that I discovered an Apple Bug:
I'm using storyboards and my rootViewController is very (very) heavy. Lots of UIVIews, UILabels, MapView, Buttons, Searcher, Embedded TableView etc. My guess is that it crashed because not all storyboard elements were initialised when viewDidLoad was called.
If this is indeed true (time will tell when I submit more builds for review) I think I either discovered a bug in iOS (as I should be able to reference IBOutlets from the storyboard in my viewDidLoad) or a discrepancy in the review process running the app, compared to actual devices running the app (as neither me nor any of my 400 beta testers is experiencing this crash).
END OF UPDATE
Based on RJE's comment I took another look at my AppDelegate to see if I was forcefully unwrapping something. I was, but to my knowledge these values could never be nil so I didn't give it another thought when I first coded it. I guess I should have.
In the build that finally got approved 3 things were different from the previous one that didn't get approved.
didFinishLaunchingWithOptions
I was forcefully unwrapping NSBundle.mainBundle().infoDictionary!["CFBundleVersion"]!
I changed
if UD.appVersion == nil || UD.appVersion != "\(NSBundle.mainBundle().infoDictionary!["CFBundleVersion"]!)" {
startClean()
UD.appVersion = "\(NSBundle.mainBundle().infoDictionary!["CFBundleVersion"]!)"
}
to this
var versionInInfoDictionary = "dummy"
if let infoDict = NSBundle.mainBundle().infoDictionary {
if let bundleVersion = infoDict["CFBundleVersion"] as? String{
versionInInfoDictionary = bundleVersion
}
else {
printError("bundleVersion nil")
}
}
else {
printError("infoDic nil")
}
if UD.appVersion == nil || UD.appVersion != versionInInfoDictionary {
startClean()
UD.appVersion = versionInInfoDictionary
}
applicationDidBecomeActive
I was forcefully unwrapping window
(defined in my AppDelegate class as var window: UIWindow?
)I changed
func applicationDidBecomeActive(application: UIApplication) {
// some code
let navController = window!.rootViewController as! CustomNavigationController
// some code
}
to this
func applicationDidBecomeActive(application: UIApplication) {
// some code
self.continueDidBecomeActive()
}
func continueDidBecomeActive() {
guard window != nil else {
printError("Window still nil")
NSTimer.scheduledTimerWithTimeInterval(0.3, target: self, selector: #selector(AppDelegate.continueDidBecomeActive), userInfo: nil, repeats: false)
return
}
if let navController = window!.rootViewController as? CustomNavigationController {
// some code
}
}
Now, I don't think it was the 3rd point that made my app crash for the App Review Team, otherwise it would have crashed on all devices and also for me.
So, it has to be either number 1, number 2 or both. Honestly I don't know and I'm still a bit confused as to why these values would be nil in any circumstance. If there are any more insights... I'd love to hear them.
I had a similar issue. No crashes on my test devices but Apple said they weren't able to start the App.
I messaged the review team in the resolution center. They started the review process again and couldn't reproduce crashes. Finally my App got accepted :)