objective c - iOS 8 push notification action buttons - code in handleActionWithIdentifier does not always run when app is in background -
i adding 2 action buttons push notifications on ios 8: accept
button , deny
button. neither button open app, different server requests made depending on button pressed. here's setup:
+ (void)requestforpushnotificationtoken { uiapplication *application = [uiapplication sharedapplication]; // if ios 8 or greater if ([application respondstoselector:@selector(registerusernotificationsettings:)]) { uimutableusernotificationaction *acceptaction = [[uimutableusernotificationaction alloc] init]; [acceptaction setactivationmode:uiusernotificationactivationmodebackground]; [acceptaction settitle:@"accept"]; [acceptaction setidentifier:@"accept_action"]; [acceptaction setdestructive:no]; [acceptaction setauthenticationrequired:no]; uimutableusernotificationaction *denyaction = [[uimutableusernotificationaction alloc] init]; [denyaction setactivationmode:uiusernotificationactivationmodebackground]; [denyaction settitle:@"deny"]; [denyaction setidentifier:@"deny_action"]; [denyaction setdestructive:no]; [denyaction setauthenticationrequired:no]; uimutableusernotificationcategory *actioncategory = [[uimutableusernotificationcategory alloc] init]; [actioncategory setidentifier:@"actionable"]; [actioncategory setactions:@[acceptaction, denyaction] forcontext:uiusernotificationactioncontextdefault]; nsset *categories = [nsset setwithobject:actioncategory]; uiusernotificationsettings *settings = [uiusernotificationsettings settingsfortypes:(uiremotenotificationtypebadge | uiremotenotificationtypesound | uiremotenotificationtypealert) categories:categories]; [application registerusernotificationsettings:settings]; } else if ([application respondstoselector:@selector(registerforremotenotificationtypes:)]) { // ios 7 or lesser uiremotenotificationtype mytypes = uiremotenotificationtypebadge | uiremotenotificationtypealert | uiremotenotificationtypesound; [application registerforremotenotificationtypes:mytypes]; } }
then, in delegate method, specifying actions taken when user pressed 1 of action buttons:
- (void)application:(uiapplication *)application handleactionwithidentifier:(nsstring *)identifier forremotenotification:(nsdictionary *)userinfo completionhandler:(void (^)())completionhandler { if ([identifier isequaltostring:@"accept_action"]) { // sending request server here } else if ([identifier isequaltostring:@"deny_action"]) { // sending request server here } if (completionhandler) { completionhandler(); } }
the ideal scenario user not need launch app in whole process; pressing accept
or deny
make different calls server. code above, seeing unstable behaviors button actions:
- a lot of times, code in action handler doesn't execute when app in background , no server calls made @ all; when happens, if tap on app icon , launch app, handler code run upon launching app.
- occasionally, handler code gets triggered , works fine. server requests made press 1 of action buttons.
- if put breakpoints in xcode , step through handler code, success rate 100%. not need launch app, , handler code gets executed when button pressed.
could please me figure out what's causing such unstable behavior? in advance.
i have figured out reason. fact works , doesn't should have given me hint sooner.
according apple documentation of application:handleactionwithidentifier:forremotenotification:completionhandler:
:
your implementation of method should perform action associated specified identifier , execute block in completionhandler parameter done. failure execute completion handler block @ end of implementation cause app terminated.
i calling completion handler @ end of application:handleactionwithidentifier:forremotenotification:completionhandler
method. however, fact sending requests server in handler code means end of implementation
not @ end of method; real end lies within callback of requests. way code it, completion handler , callback on 2 different threads, , when completion handler runs before reaches callback, it'll fail.
so solution move completion handler callback methods of request, i.e., real "end of implementation". this:
[myclient sendrequest:userinfo withsuccessblock:^(id responseobject){ nslog(@"accept - success"); if (completionhandler) { completionhandler(); } } withfailureblock:^(nserror *error, nsstring *responsestring) { nslog(@"accept - failure: %@",[error description]); if (completionhandler) { completionhandler(); } }];
Comments
Post a Comment