如何在iOS App包含扩展和扩展(不是主机应用程序)之间进行通信

时间:2014-11-19 08:14:07

标签: ios core-data swift nsnotificationcenter ios-extensions

TLDR: 是否可以在iOS App及其扩展程序之间发送实时消息或通知?

我正在编写一个iOS应用程序,其扩展名属于同一个App Group,并共享相同的CoreData(SQLite数据库)。我可以使用App中的CoreData读取和写入数据库,并且从扩展程序中,它们共享相同的内容。

我的问题是:是否可以在应用和分机之间发送消息或通知,以便在必要时通知对方进行更新?

我尝试通过NSNotificationCenter发送通知,但这并不是" out"如果我尝试写入共享NSUserDefaults的群组并听取NSUserDefaultsDidChangeNotification,则应用/扩展程序也会出现同样的问题。这适用于应用程序,但扩展程序没有收到任何东西(当我知道它已启动并且它共享相同的NSUserDefaults)。知道如何让事情保持同步吗?

4 个答案:

答案 0 :(得分:24)

TLDR: 不,但有黑客攻击

iOS应用程序没有真正的进程间通信,有或没有扩展。 NSDistributedNotification仍然没有从OS X到iOS旅行,并且可能不会。

使用某些扩展程序类型,您可以通过NSExtensionContext打开网址,并使用它们将数据传递到处理网址的应用。这会将应用程序带到前台,这听起来并不像你想要的那样。

但是有一个黑客可能会让你得到你需要的东西。

  • 不是写入用户默认值,而是写入应用程序组目录中的文件。
  • 不要直接写文件 - 使用NSFileCoordinator对文件进行协调写入。
  • 在想要了解文件更改的对象上实施NSFilePresenter,并确保致电[NSFileCoordinator addFilePresenter:someObject]
  • 在文件展示器上实施可选的presentedItemDidChange方法。

如果您完成所有这些操作,则可以从应用程序或扩展程序写入此文件,然后在另一个文件中自动调用presentedItemDidChange。作为奖励,您当然可以阅读该文件的内容,因此您可以来回传递任意数据。

答案 1 :(得分:6)

要在主机应用和应用扩展程序之间进行通用双向通信的替代方法,请尝试 MMWormhole

http://www.mutualmobile.com/posts/mmwormhole https://github.com/mutualmobile/MMWormhole

它是CFNotificationCenter的一个相当轻量级的包装器,并使用“Darwin”通知进行进程间通信(IPC)。

它传回有效载荷&使用应用程序的共享容器,甚至封装甚至必须自己创建文件。

该类(以及回购中的示例应用程序)似乎运行良好,并且反应灵敏。

我希望这也有帮助。

答案 2 :(得分:3)

您可以使用黑客在iOS或应用和扩展程序中的任意两个应用之间进行通信。唯一的事情 - 它不适用于NetworkExtension,因为Apple阻止了其中的任何I / O.

您可以通过以下方式向DarwinNotificationCenter发布通知:

    let notificationName = CFNotificationName("com.notification.name" as CFString)
    let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()

    CFNotificationCenterPostNotification(notificationCenter, notificationName, nil, nil, false)

在你的应用中添加观察者:

    let notificationName = "com.notification.name" as CFString
    let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()

    CFNotificationCenterAddObserver(notificationCenter,
                                    nil,
                                    { (
                                        center: CFNotificationCenter?,
                                        observer: UnsafeMutableRawPointer?,
                                        name: CFNotificationName?,
                                        object: UnsafeRawPointer?,
                                        userInfo: CFDictionary?
                                        ) in

                                        print("Notification name: \(name)")
                                    },
                                    notificationName,
                                    nil,
                                    CFNotificationSuspensionBehavior.deliverImmediately)

一些链接: https://github.com/choefele/CCHDarwinNotificationCenter

https://developer.apple.com/documentation/corefoundation/1542572-cfnotificationcentergetdarwinnot

https://developer.apple.com/library/content/documentation/Darwin/Conceptual/MacOSXNotifcationOv/DarwinNotificationConcepts/DarwinNotificationConcepts.html

答案 3 :(得分:2)

我一直在努力解决同样的问题,也没有找到一个干净的解决方案。解决此问题的另一种方法是简单地在扩展中运行计时器并定期检查共享容器首选项/数据库中的值,然后根据需要进行更新。不优雅,但它似乎工作。