Reputation: 1670
I'm implementing an iOS action extension, using code shared with the main app. Some of it uses [[UIApplication sharedApplication] sendAction:to:from:event]
to send actions to the first responder.
Since sharedApplication
is unavailable in an extension, this code won't compile.
I've tred one workaround, which is instanciating a UIControl
, and sending an action from it using -[UIControl sendAction:to:forEvent:]
. This works but has a big drawback (in addition to feeling very hacky): it's not possible to control the sender (this will be the UIControl
instance), which in my case is necessary.
Another workaround I'm considering is retrieving the UIApplication
object wrapping the extension by observing UIApplication notifications and getting the object
property from them (I've confirmed that some of these notifications are still sent in the extension.) But even if this did work would it have any chance to be approved by Apple, since it would just be cheating the sharedApplication
limitation? Has anybody experienced with this technique in a live app?
Thanks!
Upvotes: 2
Views: 1127
Reputation: 27550
It looks like there isn't a direct way to do this. Looking at a disassembled UIKit, there are surprisingly few methods that call -[UIApplication sendAction:to:from:forEvent:]
, and all of those explicitly provide a sender.
The good news is that -[UIControl sendAction:to:forEvent:]
is just a thin wrapper around -[UIApplication sendAction:to:from:forEvent:]
:
void -[UIControl sendAction:to:forEvent:](void * self, void * _cmd, void * arg2, void * arg3, void * arg4) {
rbx = [arg3 retain];
[*_UIApp sendAction:arg2 toTarget:rbx fromSender:self forEvent:arg4];
rdi = rbx;
[rdi release];
return;
}
If you're willing to risk that Apple might change the fundamental behavior of control interactions to completely do away with UIApplication
in extensions, it would probably be relatively safe to call sendAction:to:from:forEvent:
on a found application instance. The way I would retrieve it is view.window.nextResponder
, since this is always a UIApplication
if the window is not nil:
[(id)view.window.nextResponder sendAction:@selector(foo:) to:nil from:nil event:nil]
Apple shouldn't reject this since you aren't using disallowed API's and you aren't doing anything UIControl
isn't already doing.
If you don't want to take the risk, what you're doing is probably the best approach, creating a dummy control (if needed) and using it to send the action.
Upvotes: 2