I also encountered a very similar issue. And now, it's fixed. Hope my findings can be helpful.
By adding event tracks, I finally found the completion handlers of these functions are eventually called more than once in several async tasks!
1.
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
2.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
BTW, to help me investigate this issue, I wrapped the completion handler and passed the wrapping handler to the downstream. So, when the downside calls the wrapping completion handler, I can count the times of calling it. Then, if the wrapping completion handler is called before, it should return without calling the wrapped completion handler again.