objective c - How to troubleshoot iOS background app fetch not working? -


i trying ios background app fetch work in app. while testing in xcode works, when running on device doesn't!

  • my test device running ios 9.3.5 (my deployment target 7.1)
  • i have enabled "background fetch" under "background modes" under "capabilities" on target in xcode

enter image description here

in application:didfinishlaunchingwithoptions have tried various intervals setminimumbackgroundfetchinterval, including uiapplicationbackgroundfetchintervalminimum

- (bool)application:(uiapplication *)application didfinishlaunchingwithoptions:(nsdictionary *)launchoptions {      // tell system want background fetch     //[application setminimumbackgroundfetchinterval:3600]; // 60 minutes     [application setminimumbackgroundfetchinterval:uiapplicationbackgroundfetchintervalminimum];     //[application setminimumbackgroundfetchinterval:1800]; // 30 minutes      return yes; } 

i have implemented application:performfetchwithcompletionhandler

void (^fetchcompletionhandler)(uibackgroundfetchresult); nsdate *fetchstart;  -(void)application:(uiapplication *)application performfetchwithcompletionhandler:(void (^)(uibackgroundfetchresult))completionhandler {     fetchcompletionhandler = completionhandler;      fetchstart = [nsdate date];      [[nsuserdefaults standarduserdefaults] setobject:fetchstart forkey:klastcheckedcontentdate];     [[nsuserdefaults standarduserdefaults] synchronize];      [feedparser parsefeedaturl:url withdelegate:self]; }   -(void)onparserfinished {     ddlogverbose(@"appdelegate/onparserfinished");      uibackgroundfetchresult result = uibackgroundfetchresultnodata;      nsdate *fetchend = [nsdate date];     nstimeinterval timeelapsed = [fetchend timeintervalsincedate:fetchstart];     ddlogverbose(@"background fetch duration: %f seconds", timeelapsed);     if ([self.mostrecentcontentdate compare:item.date] < 0) {         ddlogverbose(@"got new content: %@", item.date);         self.mostrecentcontentdate = item.date;         [self schedulenotificationwithitem:item];         result = uibackgroundfetchresultnewdata;     }     else {         ddlogverbose(@"no new content.");         uilocalnotification* localnotification = [[uilocalnotification alloc] init];         localnotification.firedate = [nsdate datewithtimeintervalsincenow:60];         localnotification.alertbody = [nsstring stringwithformat:@"checked new posts in %f seconds", timeelapsed];         localnotification.timezone = [nstimezone defaulttimezone];         [[uiapplication sharedapplication] schedulelocalnotification:localnotification];     }      fetchcompletionhandler(result); } 
  • i have (successfully!) tested simulator , device using xcode's debug/simulatebackgroundfetch

  • i have tested new scheme shown in answer (https://stackoverflow.com/a/29923802/519030)

  • my tests show code executing in performfetch method in 0.3 seconds (so it's not taking long time)
  • i have verified device has background refresh enabled within settings.
  • of course, i've looked @ other questions hoping else experienced same thing. :)

when running on device , not connected xcode, code not executing. i've opened app, closed app (not killed app!), waited hours , days. have tried logging in fetch handers, , written code send local notifications.

i once saw local notifications test on device, , in fact ios seemed trigger fetch 3 times, each about fifteen minutes apart, never occurred again.

i know algorithm used determine how allow background fetch occur mystery, expect run @ least within span of days.

i @ loss else test, or how troubleshoot why seems work in simulator not on device.

appreciate advice!

your problem returning performfetchwithcompletionhandler before call completion handler, since network fetch operation occurring in background , call completion handler in delegate method. since ios thinks aren't playing rules deny ability use background fetch.

to fix problem need call beginbackgroundtaskwithexpirationhandler , end task after have called completion handler.

something like:

uibackgroundtaskidentifier backgroundtask  -(void)application:(uiapplication *)application performfetchwithcompletionhandler:(void (^)(uibackgroundfetchresult))completionhandler {     fetchcompletionhandler = completionhandler;      fetchstart = [nsdate date];      self.backgroundtask = [application beginbackgroundtaskwithexpirationhandler:^{         [application endbackgroundtask:self.backgroundupdatetask];         self.backgroundtask = uibackgroundtaskinvalid;     }];      [[nsuserdefaults standarduserdefaults] setobject:fetchstart forkey:klastcheckedcontentdate];      [feedparser parsefeedaturl:url withdelegate:self]; }  -(void)onparserfinished {     ddlogverbose(@"appdelegate/onparserfinished");      uibackgroundfetchresult result = uibackgroundfetchresultnodata;      nsdate *fetchend = [nsdate date];     nstimeinterval timeelapsed = [fetchend timeintervalsincedate:fetchstart];     ddlogverbose(@"background fetch duration: %f seconds", timeelapsed);     if ([self.mostrecentcontentdate compare:item.date] < 0) {         ddlogverbose(@"got new content: %@", item.date);         self.mostrecentcontentdate = item.date;         [self schedulenotificationwithitem:item];         result = uibackgroundfetchresultnewdata;     }     else {         ddlogverbose(@"no new content.");         uilocalnotification* localnotification = [[uilocalnotification alloc] init];         localnotification.alertbody = [nsstring stringwithformat:@"checked new posts in %f seconds", timeelapsed];         [[uiapplication sharedapplication] schedulelocalnotification:localnotification];     }     fetchcompletionhandler(result);     [[uiapplication sharedapplication] application endbackgroundtask:self.backgroundupdatetask];     self.backgroundtask = uibackgroundtaskinvalid; } 

my test app using approach has been executing fetch every 15 minutes initially, becomes less frequent on time. without background task exhibited same issue seeing.

i found setting background fetch interval other uiapplicationbackgroundfetchintervalminimum helps. test app running background fetch interval of 3600 (one hour) , has been reliably triggering several days now; after phone restart , not running app again. actual trigger interval 2-3 hours however.

my sample app here


Comments

Popular posts from this blog

amazon web services - S3 Pre-signed POST validate file type? -

c# - Check Keyboard Input Winforms -