Johnny
Johnny

Reputation: 2829

iOS Today Extension Crashing

We've added Today Extension to our app recently.

Its an extension with simple tableView to load data from our server, written in Swift.

But after the extension is online to our users, we've received lots of crash data from Crashlytics and also Apple is reporting same crash issue either.

However, we can't reproduce the crash, or even find the reason of crash, because is crashing on the widgetPerformUpdateWithCompletionHandler method which is called by the system.

Below is the detail of crash log, some information are replaced.

Crashed: com.apple.main-thread
0  MyAppWidget                    0x100091d8c MyAppWidgetViewController.(widgetPerformUpdateWithCompletionHandler((NCUpdateResult) -> ()) -> ()).(closure #1) (MyAppWidgetViewController.swift)
1  MyAppKit                       0x100603ab4 partial apply for thunk (PostService.swift)
2  MyAppKit                       0x100626080 ServiceRequestPerfomer.(performRequest(A, complete : ([B]?, NSError?) -> ()?) -> ()).(closure #1) (ServiceRequestPerformer.swift:35)
3  MyAppKit                       0x1006258d4 partial apply for ServiceRequestPerfomer.(performRequest(A, complete : ([B]?, NSError?) -> ()?) -> ()).(closure #1) (ServiceRequestPerformer.swift)
4  MyAppKit                       0x100626b34 ServiceRequestPerfomer.((request in _3C50B415180DDC893FFCB75CD7EE7019)(A, complete : (response : Response?, error : NSError?) -> ()?) -> ()).(closure #1) (ServiceRequestPerformer.swift:144)
5  Moya                           0x1004b7468 MoyaProvider.(requestNormal(A, queue : OS_dispatch_queue?, progress : (progress : ProgressResponse) -> ()?, completion : (result : Result<Response, Error>) -> ()) -> Cancellable).(closure #1).(closure #1) (Moya.swift:229)
6  Moya                           0x1004b8968 MoyaProvider.((sendAlamofireRequest in _1A5616FEE5C423A992964CB19AABD52B)(Request, target : A, queue : OS_dispatch_queue?, progress : (progress : ProgressResponse) -> ()?, completion : (result : Result<Response, Error>) -> ()) -> CancellableToken).(closure #3) (Moya.swift)
7  Moya                           0x1004b57b8 partial apply for MoyaProvider.((sendAlamofireRequest in _1A5616FEE5C423A992964CB19AABD52B)(Request, target : A, queue : OS_dispatch_queue?, progress : (progress : ProgressResponse) -> ()?, completion : (result : Result<Response, Error>) -> ()) -> CancellableToken).(closure #3) (Moya.swift)
8  Alamofire                      0x1002cff64 Request.(response(queue : OS_dispatch_queue?, completionHandler : (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> ()) -> Self).(closure #1).(closure #1) (ResponseSerialization.swift)
9  libdispatch.dylib              0x1819e14bc _dispatch_call_block_and_release + 24
10 libdispatch.dylib              0x1819e147c _dispatch_client_callout + 16
11 libdispatch.dylib              0x1819e6b84 _dispatch_main_queue_callback_4CF + 1844
12 CoreFoundation                 0x181f4cd50 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
13 CoreFoundation                 0x181f4abb8 __CFRunLoopRun + 1628
14 CoreFoundation                 0x181e74c50 CFRunLoopRunSpecific + 384
15 GraphicsServices               0x18375c088 GSEventRunModal + 180
16 UIKit                          0x18715e088 UIApplicationMain + 204
17 libxpc.dylib                   0x181c38ce0 _xpc_objc_main + 784
18 libxpc.dylib                   0x181c3a9dc xpc_main + 200
19 Foundation                     0x182a57d60 service_connection_handler + 170
20 PlugInKit                      0x18929ac48 -[PKService run] + 544
21 PlugInKit                      0x18929a8dc +[PKService main] + 56
22 PlugInKit                      0x18929ac6c +[PKService _defaultRun:arguments:] + 20
23 libextension.dylib             0x18286a058 NSExtensionMain + 64
24 libdispatch.dylib              0x181a128b8 (Missing)

And the code of widgetPerformUpdateWithCompletionHandler

func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)) {
    // Perform any setup necessary in order to update the view.
    // If an error is encountered, use NCUpdateResult.Failed
    // If there's no update required, use NCUpdateResult.NoData
    // If there's an update, use NCUpdateResult.NewData

    let options: [String: AnyObject] = [DCKPostPopularAttributeName : true.stringValue,
                                        DCKPaginationLimitAttributeName : 5]
    postService.posts(options: options) { (posts, error) in
        let historyPosts = self.userDefaults.arrayForKey(MyAppWidgetViewController.WidgetPostReadIdentifier) as? [UInt]
        if let historyPosts = historyPosts {
            self.posts = posts!.filter({ (Post) -> Bool in
                return !historyPosts.contains(Post.id)
            })
        } else {
            self.posts = posts!
        }

        self.tableView.reloadData()
        self.tableView.hidden = false;
        self.loadingLabel?.hidden = true
        self.activityIndicator?.stopAnimating()

        let contentSize = self.tableView.contentSize
        self.preferredContentSize = CGSizeMake(CGRectGetWidth(self.view.frame), contentSize.height);

        self.loadMorePostsIfNeeded()
    }
    completionHandler(NCUpdateResult.NewData)
}

The strange thing is:

  1. We haven't encountered the crash issue while we're using our Today Extension normally (It should show Unable to load if today extension crashes)

  2. We didn't receive any issue from our users reporting that today extension isn't working.

  3. We've found the same crash log on our device, but the today extension is working normally as 1. described. And also, the time of crash log recorded, I'm not using my phone!

So we're guessing it's a 「fake」crash, the crash is logged, but the extension didn't really crashed.

Does anybody facing the same issue? Thank you!

Upvotes: 1

Views: 1363

Answers (1)

Johnny
Johnny

Reputation: 2829

Answering my own question,

@matt is right, Now I am calling the completionHandler only when data fetch task completes, instead of always call the completionHandler at the last of widgetPerformUpdateWithCompletionHandler method.

I didn't receive crashes anymore, the problem was solved!

Upvotes: 2

Related Questions