Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS Crash in UIViewController.presentViewController

Tags:

ios

uikit

swift

I have an intermittent (rarely occurring) crash which, so far has only occurred in the wild with reports from AppStore. With the limited crash log, I have not been able to grok the issue.

I am trying to display an App Store Product page view. Here is the code

The enclosing class includes the SKStoreProductViewControllerDelegate  and
the delegate is set to self.

@objc func adTap(sender: UITapGestureRecognizer? = nil) -> Void {
    if  adAppID.isEmpty {return}
    let paramDict = [SKStoreProductParameterITunesItemIdentifier: adAppID]
    storeProductViewController.loadProduct(withParameters: paramDict, completionBlock: { (status: Bool, error: Error?) -> Void in
        if status {
            self.storeProductViewController.view.frame.origin.y = 0
            let eventParams = ["AppID": self.adAppID]
            self.present(self.storeProductViewController, animated: true, completion: nil)
        }
        else {
            if let error = error {
                print("Error: \(error.localizedDescription)")
            }
        }})
}

The error is triggered at the self.present:

#8  (null) in thunk for @escaping @callee_guaranteed (@unowned Bool, @guaranteed Error?) -> () ()

#7  0x100b68350 in closure #1 in ViewController.adTap(sender:)

#6  (null) in -[UIViewController presentViewController:animated:completion:] ()

#0  (null) in __exceptionPreprocess ()

Dumping the actual cashpoint file shows a SIGABRT:

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Triggered by Thread:  0

Last Exception Backtrace:
0   CoreFoundation                  0x1ad1db278 __exceptionPreprocess + 220 (NSException.m:199)
1   libobjc.A.dylib                 0x1acf040a4 objc_exception_throw + 56 (objc-exception.mm:565)
2   UIKitCore                       0x1b0bcbe0c -[UIViewController _presentViewController:withAnimationController:completion:] + 4880 (UIViewController.m:7185)
3   UIKitCore                       0x1b0bce074 __63-[UIViewController _presentViewController:animated:completion:]_block_invoke + 104 (UIViewController.m:7671)
4   UIKitCore                       0x1b0bce570 -[UIViewController _performCoordinatedPresentOrDismiss:animated:] + 508 (UIViewController.m:7772)
5   UIKitCore                       0x1b0bcdfc4 -[UIViewController _presentViewController:animated:completion:] + 196 (UIViewController.m:7678)
6   UIKitCore                       0x1b0bce22c -[UIViewController presentViewController:animated:completion:] + 160 (UIViewController.m:7716)
7   MyAppName                       0x100b68350 closure #1 in ViewController.adTap(sender:) + 1016 (ViewController.swift:991)
8   MyAppName                       0x100b68580 thunk for @escaping @callee_guaranteed (@unowned Bool, @guaranteed Error?) -> () + 60 (<compiler-generated>:0)
9   StoreKit                        0x1bba3c1e8 -[SKStoreProductViewController _loadDidFinishWithResult:error:] + 48 (SKStoreProductViewController.m:425)
10  StoreKit                        0x1bba3e624 -[SKRemoteProductViewController loadDidFinishWithResult:error:] + 128 (SKRemoteProductViewController.m:61)

///////

I understand that the completion block is an implicitly escaping block, but I do not see how it does not fulfill the block spec (arguments, if indeed that is the issue). Again, this is an intermittent event. Never seen it on a device tethered to Xcode or on one of our untethered devices. Recently it has occurred in the field, once on a iPhone 7 running iOS 13, and once on a X running 12.3.1

/////

Any thoughts would be appreciated

like image 274
BlueskyMed Avatar asked Oct 28 '25 13:10

BlueskyMed


1 Answers

Let me write this as answer, as I see now that my comment may be unclear. The block

if status {
        self.storeProductViewController.view.frame.origin.y = 0
        let eventParams = ["AppID": self.adAppID]
        self.present(self.storeProductViewController, animated: true, completion: nil)
    }

accesses some UI elements, yet it may not be running on main thread (since it's inside callback). So first thing I would suspect is that it's crashing if it happens to be called outside of main thread. Hence I would try this:

if status {
    DispatchQueue.main.async {
        self.storeProductViewController.view.frame.origin.y = 0
        let eventParams = ["AppID": self.adAppID]
        self.present(self.storeProductViewController, animated: true, completion: nil) 
    }
}

If it helps, maybe think of better MVC separation...

like image 55
ytrewq Avatar answered Oct 30 '25 05:10

ytrewq