如何以编程方式在iOS扩展中发送操作,因为`sharedApplication`不可用?

时间:2016-01-12 14:18:56

标签: ios objective-c cocoa-touch uikit

我正在使用与主应用共享的代码实现iOS动作扩展。其中一些使用[[UIApplication sharedApplication] sendAction:to:from:event]向第一响应者发送动作。 由于sharedApplication在扩展中不可用,因此此代码将无法编译。

我尝试了一种解决方法,即实现UIControl,并使用-[UIControl sendAction:to:forEvent:]从中发送操作。这有效,但有一个很大的缺点(除了感觉非常hacky):它不可能控制发送者(这将是UIControl实例),在我的情况下是必要的。

我正在考虑的另一个解决方法是通过观察UIApplication通知并从中获取UIApplication属性来检索包装扩展的object对象(我已经确认其中一些通知仍在发送中)延期。)但即使这确实有效,它是否有机会被Apple批准,因为它会欺骗sharedApplication限制?有没有人在现场应用中体验过这种技术?

谢谢!

1 个答案:

答案 0 :(得分:2)

看起来没有直接的方法来做到这一点。看一下反汇编的UIKit,很少有方法调用-[UIApplication sendAction:to:from:forEvent:],所有这些方法都明确地提供了发送者。

好消息是-[UIControl sendAction:to:forEvent:]只是-[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;
}

如果您愿意承担风险,Apple可能会更改控件互动的基本行为,以完全取消UIApplication扩展程序,那么在sendAction:to:from:forEvent:上调用view.window.nextResponder可能相对安全找到应用实例。我检索它的方式是UIApplication,因为如果窗口不是nil,它总是[(id)view.window.nextResponder sendAction:@selector(foo:) to:nil from:nil event:nil]

UIControl

Apple不应该拒绝这一点,因为你没有使用不允许使用的API,而且你还没有做任何PlotOrientation已经做过的事情。

如果您不想承担风险,那么您所做的可能是最好的方法,创建虚拟控件(如果需要)并使用它来发送操作。