我想在今天的扩展程序(Widget)中管理包含应用程序的操作。
完整描述: 在我的应用程序中,一些动作(如播放/暂停音频)执行。并希望从今天的扩展(小部件)管理该操作。动作也继续在后台状态下执行。
在今天的扩展中,将执行相同的操作。因此,如果在主要包含应用程序中已经启动操作并将其发送到后台状态,则用户可以暂停窗口小部件的操作。用户也可以随时从小部件(今天的扩展名)开始/暂停操作。
为了实现这一目标,我使用UserDefault和app Group功能并存储一个布尔值。当小部件出现时,它检查布尔值并设置按钮状态播放/暂停。它设置正确,但当我按下扩展按钮时,操作无法在主机应用程序中执行。
代码:
主要包含应用代码
override func viewDidLoad() {
super.viewDidLoad()
let objUserDefault = UserDefaults(suiteName:"group.test.TodayExtensionSharingDefaults")
let objTemp = objUserDefault?.object(forKey: "value")
self.btnValue.isSelected = objTemp
NotificationCenter.default.addObserver(self, selector: #selector(self.userDefaultsDidChange), name: UserDefaults.didChangeNotification, object: nil)
}
func userDefaultsDidChange(_ notification: Notification) {
let objUserDefault = UserDefaults(suiteName: "group.test.TodayExtensionSharingDefaults")
objUserDefault?.synchronize()
let objTemp = objUserDefault?.object(forKey: "value")
self.btnValue.isSelected = objTemp
}
在分机类中:
@IBAction func onPlayPause(_ sender: UIButton) {
DispatchQueue.main.async {
let sharedDefaults = UserDefaults(suiteName: "group.test.TodayExtensionSharingDefaults")
if let isPlaying = sharedDefaults?.bool(forKey: "isPlaing") {
sharedDefaults?.set(!isPlaying, forKey: "isPlaying")
}else{
sharedDefaults?.set(false, forKey: "isPlaying")
}
sharedDefaults?.synchronize()
}
用户更新默认值时未触发通知。它是应用重启时的更新值。
那么如何解决这个问题?
同样的事情想要从包含应用程序到小部件的相反方式做。 (易于用户单一操作对象,但如何?)
还有其他方法可以在不打开App的情况下从扩展程序中包含应用程序的快速操作吗?
答案 0 :(得分:9)
使用MMWormhole
(或其新的和非官方的Swift版本,只需Wormhole
)。这很简单。
在应用程序的视图控制器中:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let wormhole = MMWormhole(applicationGroupIdentifier: "group.test.TodayExtensionSharingDefaults",
optionalDirectory: "TodayExtensionSharingDefaults")
wormhole.listenForMessage(withIdentifier: "togglePlayPause") { [weak self] _ in
guard let controller = self else { return }
controller.btnValue.isSelected = controller.btnValue.isSelected
}
}
在扩展程序中:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view from its nib.
self.wormhole = MMWormhole(applicationGroupIdentifier: "group.test.TodayExtensionSharingDefaults", optionalDirectory: "TodayExtensionSharingDefaults")
}
@IBAction func onPlayPause(_ sender: UIButton) {
guard let wormhole = self.wormhole else { extensionContext?.openURL(NSURL(string: "foo://startPlaying")!, completionHandler: nil) } // Throw error here instead of return, since somehow this function was called before viewDidLoad (or something else went horribly wrong)
wormhole.passMessageObject(nil, identifier: "togglePlayPause")
}
在Xcode的文档类型部分,在网址下声明foo://
(或您使用的任何其他内容),然后在AppDelegate
中实施application(_:open:options:)
,以便在网址传递时应用开始播放音乐是foo://startPlaying
。
答案 1 :(得分:4)
创建自定义网址Scehme
检查组数据。(您设置是否正确)
每当您点击按钮时,将从 Appdelegate , UIApplication 代表
调用主机应用func application(_ application: UIApplication, open urls: URL, sourceApplication: String?, annotation: Any) -> Bool {
let obj = urls.absoluteString.components(separatedBy: "://")[1]
NotificationCenter.default.post(name: widgetNotificationName, object: obj)
print("App delegate")
return true
}
从那里发出通知,然后在你的hostapp的任何地方观察。
小工具按钮操作代码
@IBAction func doActionMethod(_ sender: AnyObject) {
let button = (sender as! UIButton)
var dailyThanthi = ""
switch button.tag {
case 0:
dailyThanthi = "DailyThanthi://h"
case 1:
dailyThanthi = "DailyThanthi://c"
case 2:
dailyThanthi = "DailyThanthi://j"
// case 3:
// dailyThanthi = "DailyThanthi://s"
// case 4:
// dailyThanthi = "DailyThanthi://s"
default:
break
}
let pjURL = NSURL(string: dailyThanthi)!
self.extensionContext!.open(pjURL as URL, completionHandler: nil)
}
注意:
应用扩展程序与其之间没有直接通信 包含app;通常,包含应用程序甚至不运行 包含的扩展名正在运行。包含应用的应用扩展程序 并且主机应用程序根本不进行通信。
在典型的请求/响应事务中,系统代表主机应用程序打开应用程序扩展,在扩展中传送数据 上下文由主持人提供。扩展程序显示用户界面, 执行一些工作,并且,如果适合扩展的目的, 将数据返回给主机。
图2-2中的虚线表示应用扩展程序与其包含应用程序之间可用的有限交互。今天 小部件(没有其他应用程序扩展类型)可以要求系统打开 它包含的应用程序通过调用
openURL:completionHandler:
方法NSExtensionContext
课程。<activity android:name=".your activity" android:theme="xxxx"></activity>
。如中的读/写箭头所示 图2-3,任何应用程序扩展及其包含的应用程序都可以访问共享 私有定义的共享容器中的数据。完整的词汇 扩展,其主机应用程序及其包含之间的通信 app在图2-3中以简单的形式显示。