【问题标题】:How to programmatically send an action in an iOS extension, since `sharedApplication` is unavailable?由于“sharedApplication”不可用,如何以编程方式在 iOS 扩展中发送操作?
【发布时间】:2016-01-12 14:18:55
【问题描述】:

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

我尝试了一种解决方法,即实例化一个UIControl,并使用-[UIControl sendAction:to:forEvent:] 从它发送一个动作。这可行,但有一个很大的缺点(除了感觉很hacky):无法控制发件人(这将是UIControl 实例),在我的情况下这是必要的。

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

谢谢!

【问题讨论】:

  • 我对相同的功能感兴趣。你找到正确的方法来实现它了吗?
  • 我不满意。我实例化了一个假的 UIControl 子类实例,如第二段中所述,我将 nextResponder 设置为我感兴趣的实际发送者。

标签: ios objective-c cocoa-touch uikit


【解决方案1】:

看起来没有直接的方法可以做到这一点。查看拆解后的 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

[(id)view.window.nextResponder sendAction:@selector(foo:) to:nil from:nil event:nil]

Apple 不应该拒绝这一点,因为您没有使用不允许的 API,并且您没有做任何 UIControl 尚未做的事情。

如果您不想冒险,您正在做的可能是最好的方法,创建一个虚拟控件(如果需要)并使用它来发送操作。

【讨论】:

  • 有趣的见解,谢谢。我没有检查UIControl 的实现,但你提供的反汇编让我在使用我目前的方法时感到安慰。我宁愿远离UIApplication 这样做,因为随着扩展的出现,我不希望它仍然可以访问。我还没有检查是否有希望使用 iOS 10 进行干净的实现,但我会的,如果有的话,我会在这里发布我的发现。
  • 叙述者的声音:他没有
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-15
  • 2019-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多