App Crashes After Executing Background Fetch Completionhandler

Swift3 - Background Fetch Crash on Debug

As per your above description, I tried it in my project but it works fine and performFetchWithCompletionHandler is working in background also.

First I try without adding this property, but performFetchWithCompletionHandler not called. So,Try to add this in info.plist file

 <key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>

It will solve my problem

App crashes at reloadData() for Collectionview with a background fetch

Don't initialize PublicationOverviewController() again because it will give you new instance of that view and you would not get your referenced collectionView. Also you will get all UI controls nil before viewDidLoad: get calls.

Example:

let *controller : PublicationOverviewController = PublicationOverviewController()
// controller.collectionView will be nil here because view hasn't loaded yet

What you can do Post a notification in applicationDidBecomeActive: method and observe it in PublicationOverviewController then reload your collectionView in respective method.

Background performFetchWithCompletionHandler using Blocks causes crash

self.completionHandler = UIBackgroundFetchResultNewData; 

does not match types. completionHandler is of type (void (^)(UIBackgroundFetchResult)) while UIBackgroundFetchResultNewData is of type NSUInteger.

typedef enum : NSUInteger {
UIBackgroundFetchResultNewData,
UIBackgroundFetchResultNoData,
UIBackgroundFetchResultFailed
} UIBackgroundFetchResult;

So when you call self.completionHandler (YES), self.completionHandler is an NSUInteger, so NSUInteger(YES) doesn't make much sense.

Correct use of background fetch completion handler

Update your getZoneChanges to have a completion parameter.

func getZoneChanges(completion: @escaping (Bool) -> Void) {
// the rest of your code

operation.fetchRecordZoneChangesCompletionBlock = { (error) in
if let error = error {
print("Error fetching zone changes: \(error.localizedDescription)")

completion(false)
} else {
print("Changes fetched successfully!")

completion(true)
}
}
}

Then you can update the app delegate method to use it:

func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
DispatchQueue.global(qos: .userInitiated).async {
// Code to get a reference to main view controller
destinationViewController.getZoneChanges { (success) in
completionHandler(success ? .newData : .noData)
}
}
}


Related Topics



Leave a reply



Submit