I want to manage some action in containing app from today extension(Widget).
Full description: in my containing app, some action (like play/pause audio) perform. And want to manage that action also from today extension(widget). An action continues to perform in background state as well.
In today extension, the same action will perform. so for that, if in the main containing app already starts an action and send it into background state, a user can pause action from a widget. and the user also can start/pause action any time from the widget (today extension).
For achieve this goal I used UserDefault with app Group capability and store one boolean value. when widget present it checks boolean value and set button state play/pause. it's set correctly but when I press extension button action does not perform in host app.
code:
in main containing app code
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
}
In Extension Class:
@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()
}
notification was not fired when a user updates default. it's updated value when the app restarts.
so how to solve this issue?
and the same thing wants to do in opposite means from containing app to a widget. (easy to user single action object but how?)
And is any other way to perform a quick action in containing app from extension without opening App?
Use
MMWormhole
(or its new and unofficial Swift version, justWormhole
). It's very simple.In the app's view controller:
In the extension:
Declare
foo://
(or whatever else you use) in Xcode's Document Types section, under URLs, then implementapplication(_:open:options:)
in yourAppDelegate
so that the app starts playing music when the URL passed isfoo://startPlaying
.