ios swift swift3 today-extension

Realice acciones en la aplicación host desde la extensión Today(Widget) sin abrir las aplicaciones ios



swift swift3 (2)

  1. Crear URL personalizada Sceheme

  2. Verifique los datos de los grupos (está configurando correctamente o no)

  3. Cada vez que haga clic en el botón, se llamará a la aplicación host desde Appdelegate , delegado de 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. Encienda su notificación desde allí y obsérvela en cualquier lugar de su alojamiento.

    Código de acción del botón del widget

    @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. Verifique el tipo de URL personalizado: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Inter-AppCommunication/Inter-AppCommunication.html

  6. Nota:

    No hay comunicación directa entre una extensión de aplicación y su aplicación contenedora; por lo general, la aplicación que contiene ni siquiera se está ejecutando mientras se está ejecutando una extensión contenida. La aplicación que contiene una extensión de la aplicación y la aplicación host no se comunican en absoluto.

    En una transacción de solicitud / respuesta típica, el sistema abre una extensión de aplicación en nombre de una aplicación host, que transmite datos en un contexto de extensión provisto por el host. La extensión muestra una interfaz de usuario, realiza algunos trabajos y, si es apropiado para el propósito de la extensión, devuelve los datos al host.

    La línea de puntos en la Figura 2-2 representa la interacción limitada disponible entre una extensión de la aplicación y su aplicación contenedora. Un widget de Hoy (y ningún otro tipo de extensión de aplicación) puede pedirle al sistema que abra su aplicación contenedora llamando al openURL:completionHandler: de la clase NSExtensionContext . Como lo indican las flechas de Lectura / Escritura en la Figura 2-3, cualquier extensión de la aplicación y su aplicación contenedora pueden acceder a los datos compartidos en un contenedor compartido definido de forma privada. El vocabulario completo de comunicación entre una extensión, su aplicación anfitriona y la aplicación que lo contiene se muestra de forma sencilla en la Figura 2-3.

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

Quiero gestionar alguna acción en la extensión que contiene la aplicación de hoy (Widget).

Descripción completa: en mi aplicación que contiene, se realiza alguna acción (como reproducir / pausar audio). Y quiero gestionar esa acción también desde la extensión de hoy (widget). Una acción continúa ejecutándose también en estado de fondo.

En la extensión de hoy, se realizará la misma acción. para eso, si en la aplicación que contiene principal ya comienza una acción y la envía al estado en segundo plano, un usuario puede pausar la acción desde un widget. y el usuario también puede iniciar / pausar la acción en cualquier momento desde el widget (extensión de hoy).

Para lograr este objetivo, utilicé UserDefault con la capacidad de grupo de aplicaciones y almacené un valor booleano. cuando el widget presenta el valor booleano y establece el estado del botón reproducir / pausar. está configurado correctamente, pero cuando presiono la acción del botón de extensión no se realiza en la aplicación host.

código:

en el código principal de la aplicación que contiene

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 }

En la clase de extensión:

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

la notificación no se activó cuando un usuario actualiza el valor predeterminado. Se actualiza el valor cuando la aplicación se reinicia.

Entonces, ¿cómo resolver este problema?

y lo mismo se quiere hacer en medios opuestos de contener la aplicación a un widget. (Fácil de usar objeto de una sola acción, pero ¿cómo?)

¿Y hay alguna otra forma de realizar una acción rápida para contener la aplicación desde la extensión sin abrir la aplicación?


Use MMWormhole (o su nueva y no oficial versión Swift, solo Wormhole ). Es muy sencillo.

En el controlador de vista de la aplicación:

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

En la extensión:

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

Declare foo:// (o cualquier otra cosa que use) en la sección de Tipos de documentos de Xcode, debajo de las URL, luego implemente la application(_:open:options:) en su AppDelegate para que la aplicación comience a reproducir música cuando la URL aprobada sea foo://startPlaying .