Apple claims the app crashes on startup during review, can't even closely reproduce

Hi. Striggling with that for approximately a month. Apple claims the app crashes on startup, but working for me on devices, simulators, debug/release/adhoc without any problems. Was crashing even on TestFlight testing, after 8 attempts got it accepted for external testers (Crashlytics reported it crashed for them though). The crashes occur in function which saves cached images to the Caches directory. First versions was written using NSSearchPathForDirectoriesInDomains, then I've changed it to NSFileManager but without any luck.


The code:

class SharedAux {
    static let shared = SharedAux()


    func downloadAndCacheImg(url: String?, cell: AppCell, tableView: UITableView, indexPath: NSIndexPath) {
        if url == nil { return }
      
        let charactersToRemove = NSCharacterSet.alphanumericCharacterSet().invertedSet
        let cacheFilename = "".join(url!.componentsSeparatedByCharactersInSet(charactersToRemove))
       
        if let fullFilename = prefixFilenameWithDirectory(cacheFilename), img = UIImage(named: fullFilename) {
            cell.setAppImage(img)
            return
        }
        if let nsUrl = NSURL(string: url!) {
            NSURLConnection.sendAsynchronousRequest(NSURLRequest(URL: nsUrl), queue: NSOperationQueue.mainQueue(), completionHandler: { (response, data, error) -> Void in
                if let img = UIImage(data: data) {                                             // CRASH HERE
                    if let fullFilename = self.prefixFilenameWithDirectory(cacheFilename) {
                        data.writeToFile(fullFilename, atomically: true)
                    }
                    if let cell = tableView.cellForRowAtIndexPath(indexPath) as? AppCell {
                        cell.setAppImage(img)
                    }
                }
            })
        }
    }
  
    func prefixFilenameWithDirectory(filename: String) -> String? {
        var dir = NSFileManager.defaultManager().URLForDirectory(.CachesDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true, error: nil)
        dir = dir?.URLByAppendingPathComponent(filename)
        return dir?.path
    }


The symbolicated crash log:

Incident Identifier: 79EF86C1-42A2-4398-AE8D-96294CA44779
CrashReporter Key:   9e383a79712622f70c441c3e542088b4ff8f5801
Hardware Model:      ***
Process:             yyy [2793]
Path:                /private/var/mobile/Containers/Bundle/Application/161F43F5-7E46-4963-AC86-B1CF5634FB47/yyy.app/yyy
Identifier:          com.rshev.yyy
Version:             80 (0.9)
Code Type:           ARM-64 (Native)
Parent Process:      launchd [1]


Date/Time:           2015-07-02 16:11:15.810 -0700
Launch Time:         2015-07-02 16:11:07.032 -0700
OS Version:          iOS 8.3 (12F69)
Report Version:      105


Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000100099e54
Triggered by Thread:  0


Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   navTo                         0x0000000100099e54 navTo.SharedAux.(downloadAndCacheImg (navTo.SharedAux) -> (Swift.String?, cell : navTo.AppCell, tableView : ObjectiveC.UITableView, indexPath : ObjectiveC.NSIndexPath) -> ()).(closure #1) (SharedAux.swift:29)
1   navTo                         0x0000000100099628 partial apply forwarder for navTo.SharedAux.(downloadAndCacheImg (navTo.SharedAux) -> (Swift.String?, cell : navTo.AppCell, tableView : ObjectiveC.UITableView, indexPath : ObjectiveC.NSIndexPath) -> ()).(closure #1) (SharedAux.swift:0)
2   CFNetwork                     0x000000018546b30c 0x1853cc000 + 652044
3   Foundation                     0x000000018698f1c0 0x1868b4000 + 897472
4   Foundation                     0x00000001868e0600 0x1868b4000 + 181760
5   Foundation                     0x00000001868d01c8 0x1868b4000 + 115144
6   Foundation                     0x0000000186991f24 0x1868b4000 + 909092
7   libdispatch.dylib             0x0000000197819950 0x197818000 + 6480
8   libdispatch.dylib             0x000000019781e208 0x197818000 + 25096
9   CoreFoundation                 0x0000000185a5f7f4 0x185980000 + 915444
10  CoreFoundation                 0x0000000185a5d89c 0x185980000 + 907420
11  CoreFoundation                 0x00000001859892d0 0x185980000 + 37584
12  GraphicsServices               0x000000018f0776f8 0x18f06c000 + 46840
13  UIKit                         0x000000018a54efa8 0x18a4d8000 + 487336
14  navTo                         0x0000000100098428 main (AppDelegate.swift:15)
15  libdyld.dylib                 0x0000000197846a04 0x197844000 + 10756


Thread 1 name:  Dispatch queue: com.apple.libdispatch-manager


Please give any ideas, really stuck here.

Answered by hotngui in 21036022

It it truly is crashing at line 17 as you suggest its probably because you are assuming you did not get an error and that "data" is valid. Perhaps the reason you are seeing from other users is that you have a firewall or other URL related issue where you have access, but others do not?

Maybe this is producing some form of infinite recursion:


class SharedAux {
     static let shared = SharedAux()
     // ...

}
Accepted Answer

It it truly is crashing at line 17 as you suggest its probably because you are assuming you did not get an error and that "data" is valid. Perhaps the reason you are seeing from other users is that you have a firewall or other URL related issue where you have access, but others do not?

This is a standard swift singleton.

  1. if let nsUrl = NSURL(string: url!) {
  2. NSURLConnection.sendAsynchronousRequest(NSURLRequest(URL: nsUrl), queue: NSOperationQueue.mainQueue(), completionHandler: { (response, data, error) -> Void in
  3. if let img = UIImage(data: data) { // CRASH HERE


Is that the right way to specify a completion handler with possibly nil paramters?


I'm not sure how UIImage(nil) reacts in Swift, but never running into the data==nil case when testing locally, but having external testers run into that case, is one of the classic "The network hates us" type bugs.

UIImage(nil) will crash. The data parameter is annotated as nonnull, meaning you can never pass in a nil pointer.


You need to check the data parameter for nil before you try to create the image. Check the response code, that may give you a clue as to why the data is nil.

>Apple claims the app crashes on startup, but working for me on devices, simulators, debug/release/adhoc without any problems


Did you try an ad-hoc install...that may better replicate a store install/Apple's testing. As well, it might be a case of the OS killing your app on start for some reason, vs. an outright/logged crash. What does Instruments show?

Added testing data for nil, high probability that this will not crash, because I realized that data in closure is not declared as optional.


Another question, of course, why am I getting data but Apple review team gets error, maybe they are restricting their review environment by some firewall.

Posted a TestFlight build for review, waiting to see if it's crashing now.

FIXED: the build passed TestFlight review successfully. Thanks for the tips!

Another question, of course, why am I getting data but Apple review team gets error, maybe they are restricting their review environment by some firewall.


The question should not be about Apple testers behind a firewall. In your coding and testing, you should assume that your users may not always be able to access the network and handle that accordingly.

Apple claims the app crashes on startup during review, can't even closely reproduce
 
 
Q