2016-12-28 9 views
16

今日の拡張機能(ウィジェット)からアプリを含む際に何らかのアクションを管理したい。今日の拡張機能(ウィジェット)からホストアプリケーションでアクションを実行するアプリケーションを開くことなし

詳細: 私の含むアプリでは、何らかのアクション(再生/一時停止オーディオなど)が実行されます。また、今日の拡張機能(ウィジェット)からもそのアクションを管理したいと考えています。アクションはバックグラウンド状態でも引き続き実行されます。

今日の拡張では、同じ動作が実行されます。そのため、メインのアプリケーションが既にアクションを開始し、それをバックグラウンド状態にすると、ユーザーはウィジェットからアクションを一時停止できます。ユーザーはいつでもウィジェット(今日の拡張機能)からアクションを開始/一時停止することができます。

私はこの目標を達成するために、Appのグループ機能を持つUserDefaultを使用し、1つのブール値を保存しました。ウィジェットが存在するときブール値をチェックし、ボタン状態の再生/一時停止を設定します。それは正しく設定されていますが、拡張ボタンを押すと、ホストアプリケーションではアクションが実行されません。

コード:拡張クラスで

メイン含むアプリのコードで

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() 
} 

通知が発射されませんでした。アプリが再起動したときに更新された値です。

どのようにこの問題を解決するには?

と同じことが、アプリをウィジェットに格納することとは逆の意味でしたいと考えています。 (簡単なユーザアクションオブジェクトです)

また、アプリケーションを開かずに拡張機能からアプリケーションを含む際に、すばやいアクションを実行する方法はありますか?

+0

? – karthikeyan

答えて

9

MMWormhole(またはその新しい非公式のSwiftバージョン、ちょうどWormhole)を使用してください。それはとても簡単です。その後、Xcodeののドキュメントの種類]セクションで

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") 
} 

宣言foo://(または任意の他使用)、URLの下、内application(_:open:options:)を実装:延長で

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 
    } 
} 

:アプリのビューコントローラで

あなたのAppDelegateが渡され、URLがfoo://startPlayingのときにアプリが音楽の再生を開始します。

how to add URL to Xcode

+0

アプリが非アクティブ状態でバックグラウンドのときにこのライブラリが動作しない –

+0

アプリが実行されていない場合、音楽はどのように始まりますか? – Coder256

+0

それが問題です。 playAndRecordを開始して停止したい –

4
  1. カスタムURL Sceheme

  2. チェックグループのデータを作成します。

  3. ボタンをクリックするたび

    、ホストアプリは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 
        } 
    
  4. デリゲートから呼ばれます(あなたの設定は正しいかされていません)あなたの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) 
    
    } 
    
  5. チェックアウトカスタムURLのタイプ: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Inter-AppCommunication/Inter-AppCommunication.html

  6. 注:

    アプリの拡張との間には直接の通信はありませんそのアプリを含む ;含まれているアプリケーションが実行中でなく、含まれている拡張機能が実行されている間に、通常はが実行されます。アプリ拡張を含むアプリ とホストアプリはまったく通信しません。

    一般的なリクエスト/応答トランザクションでは、システムはホストアプリケーションの代わりにアプリケーション拡張を開き、ホストによって提供された内線番号 のコンテキストでデータを伝達します。拡張機能はユーザーインターフェイスを表示し、 は何らかの作業を行い、拡張機能の目的に応じて はデータをホストに返します。

    図2-2の点線は、アプリエクステンションとそのアプリを含むアプリの間で利用できる限定的なやりとりを表しています。今日は ウィジェット(その他のアプリ拡張タイプはありません) のアプリケーションを含むopenURL:completionHandler:メソッドを NSExtensionContextクラスを呼び出すことによって開くことができます。 図2-3の読み取り/書き込み矢印に示すように、任意のアプリリンクとそのアプリを含むアプリは、非公開の共有コンテナ内の共有 データにアクセスできます。拡張子、そのホストアプリケーション、およびそれに含まれる アプリケーションの間の 通信の完全な語彙は、図2-3に簡単な形式で示されています。あなたの通知を発射している

    https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionOverview.html

+0

ポイント3と4が得られない場合は、より適切に説明してください。 –

+0

これはあなたのアプリを開いて、6点を確認します。しかし、あなたはアプリを開くことなく言っている、私はそれが可能ではないと思う、ドキュメントをチェックしてください。 – karthikeyan

関連する問題