Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从今天开始在主机应用程序(小部件)中执行操作,无需打开应用程序ios_Ios_Swift_Swift3_Today Extension - Fatal编程技术网

从今天开始在主机应用程序(小部件)中执行操作,无需打开应用程序ios

从今天开始在主机应用程序(小部件)中执行操作,无需打开应用程序ios,ios,swift,swift3,today-extension,Ios,Swift,Swift3,Today Extension,我想在包含应用程序from today扩展(小部件)中管理一些操作 详细说明: 在我的应用程序中,执行一些操作(如播放/暂停音频)。并且希望从今天开始管理该操作扩展(widget)。操作也会在后台状态下继续执行 在今天的扩展中,将执行相同的操作。因此,如果主应用程序中已经启动了一个动作并将其发送到后台状态,用户可以暂停小部件中的动作。用户还可以随时从小部件启动/暂停操作(今天扩展) 为了实现这个目标,我使用了UserDefault和appgroup功能,并存储了一个布尔值。当小部件出现时,它检查

我想在包含应用程序from today扩展(小部件)中管理一些操作

详细说明: 在我的应用程序中,执行一些操作(如播放/暂停音频)。并且希望从今天开始管理该操作扩展(widget)。操作也会在后台状态下继续执行

在今天的扩展中,将执行相同的操作。因此,如果主应用程序中已经启动了一个动作并将其发送到后台状态,用户可以暂停小部件中的动作。用户还可以随时从小部件启动/暂停操作(今天扩展)

为了实现这个目标,我使用了UserDefault和appgroup功能,并存储了一个布尔值。当小部件出现时,它检查布尔值并设置按钮状态“播放/暂停”。它设置正确,但当我按下扩展按钮时,主机应用程序中不会执行该操作

代码:

主要包含应用程序代码

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()
}
用户更新默认值时未触发通知。当应用程序重新启动时,它会更新值

那么如何解决这个问题呢

同样的事情也要以相反的方式完成,从包含应用程序到小部件。 (易于使用单个动作对象,但如何操作?)

还有没有其他方法可以在不打开应用程序的情况下从extension中包含应用程序而执行快速操作?

使用(或其新的非官方Swift版本,仅此而已)。这很简单

在应用程序的视图控制器中:

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的“文档类型”部分的URL下声明
foo://
(或您使用的任何其他内容),然后在
AppDelegate
中实现,以便当传递的URL为
foo://startPlaying

  • 创建自定义URL主题

  • 检查组数据。(设置是否正确)

  • 每当您单击按钮时,主机应用程序将从AppdelegateUIApplicationdelegate调用

    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)
    
    }
    
  • 签出自定义url类型:

  • 注:

    应用程序扩展和其应用程序之间没有直接通信 包含应用程序;通常,包含应用程序的应用程序在运行时甚至没有运行 包含的扩展正在运行。包含应用程序的应用程序扩展 而且主机应用程序根本不通信

    在典型的请求/响应事务中,系统代表主机应用打开应用程序扩展,在扩展中传输数据 主机提供的上下文。扩展显示一个用户界面, 执行一些工作,如果适用于扩展的目的, 将数据返回到主机

    图2-2中的虚线表示应用程序扩展与其包含的应用程序之间可用的有限交互。A今天 widget(没有其他应用程序扩展类型)可以请求系统打开 它通过调用
    NSExtensionContext
    类。如中的读/写箭头所示 图2-3,任何应用程序扩展及其包含的应用程序都可以访问共享 私有定义的共享容器中的数据。英语的全部词汇 扩展、其主机应用程序和其包含应用程序之间的通信 app在图2-3中以简单形式显示


  • 你在哪里发布通知?没有得到第3点和第4点。你能解释得更清楚些吗。这会打开你的应用程序,检查6分。但是你说不打开应用程序,我认为这是不可能的,检查文档。嗨,当应用程序处于非活动状态时,这个库不工作,如果应用程序不运行,音乐将如何启动?这就是问题所在。要开始和停止播放和录制库(Swift)已三年未更新。也许是不。