2016-12-28 31 views
16

Chcę zarządzać działaniami związanymi z aplikacją z rozszerzeniem dzisiaj (Widget).Wykonaj akcję w aplikacji hosta z rozszerzenia Dzisiaj (Widget) Bez otwierania aplikacji ios

Pełny opis: w mojej aplikacji zawierającej niektóre działania (np. Odtwarzanie/wstrzymanie dźwięku) działają. I chcesz zarządzać tą akcją również z dzisiejszego rozszerzenia (widgetu). Akcja nadal działa również w tle.

W dniu dzisiejszym zostanie wykonana ta sama czynność. więc jeśli w głównej aplikacji zawierającej już rozpoczyna działanie i wysłać go do stanu w tle, użytkownik może wstrzymać działanie z widgetu. a użytkownik może także rozpocząć/wstrzymać działanie w dowolnym momencie z poziomu widgetu (dzisiejsze rozszerzenie).

Aby osiągnąć ten cel, użyłem UserDefault z funkcją Group app i zapamiętałem jedną wartość boolowską. gdy widżet prezentuje, sprawdza wartość boolowską i ustawia stan przycisku pauza/odtwarzanie. jest ustawiony prawidłowo, ale kiedy naciskam przycisk rozszerzenia, akcja nie działa w aplikacji hosta. Kod

:

w głównym zawierającym kod aplikacji

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 
    } 

W klasie Extension:

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

notyfikacji nie został zwolniony, gdy domyślny aktualizacje użytkowników. zaktualizowana wartość po ponownym uruchomieniu aplikacji.

, jak rozwiązać ten problem?

i to samo, co chce zrobić w przeciwnych środkach, od umieszczenia aplikacji w widgecie. (łatwy do pojedynczego użytkownika obiekt, ale jak?)

Czy jest jakikolwiek inny sposób na szybkie działanie w zakresie zawierania aplikacji z rozszerzenia bez otwierania aplikacji?

+0

Dokąd wypalanie swoje zgłoszenie? – karthikeyan

Odpowiedz

9

Użyj MMWormhole (lub jego nowej i nieoficjalnej wersji Swift, tylko Wormhole). To jest bardzo proste.

w App widoku kontrolera:

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

W rozszerzenia:

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:// (lub cokolwiek innego wykorzystania) w sekcji Typy dokumentów Xcode jest pod adresami URL, a następnie wdrożyć application(_:open:options:) w Twój numer AppDelegate, aby aplikacja zaczęła odtwarzać muzykę po przekazaniu adresu URL pod numerem foo://startPlaying.

how to add URL to Xcode

+0

Witaj, ta biblioteka nie działa, gdy aplikacja jest w stanie nieaktywnym i jest w tle. –

+0

Jeśli aplikacja nie jest uruchomiona, jak będzie odtwarzana muzyka? – Coder256

+0

To jest problem. Chcesz zacząć i zatrzymać playAndRecord –

4
  1. Tworzenie niestandardowego URL Sceheme

  2. Sprawdź grup danych.(Czy ustawienie poprawne, czy nie)

  3. po kliknięciu na przycisk, aplikacja hosta zostanie sprawdzony z Appdelegate, UIApplication delegat

    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. Ogień powiadomienie stamtąd następnie obserwować gdziekolwiek w twoim hostappie.

    Widget Przycisk działanie kodu

    @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. Wyjazd niestandardowy typ url: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Inter-AppCommunication/Inter-AppCommunication.html

  6. Uwaga:

    Nie ma bezpośredniej komunikacji między rozszerzeniem aplikacji i jej zawierająca aplikację; zazwyczaj aplikacja zawierająca nawet nie działa, gdy uruchomione jest dostępne rozszerzenie. Rozszerzenie aplikacji zawierające aplikację i aplikacja hosta w ogóle się nie komunikują.

    W typowej transakcji żądania/odpowiedzi system otwiera rozszerzenie aplikacji w imieniu aplikacji hosta, przekazując dane w rozszerzeniu kontekście dostarczonym przez hosta. Rozszerzenie wyświetla interfejs użytkownika, wykonuje pewną pracę i, jeśli jest to właściwe dla celów rozszerzenia, zwraca dane do hosta.

    Linia przerywana na Rysunku 2-2 przedstawia ograniczone interakcje między rozszerzeniem aplikacji i jej aplikacją. Widget Dzisiaj (i żaden inny typ rozszerzenia aplikacji) może poprosić system o otwarcie swojej aplikacji zawierającej, dzwoniąc pod numer openURL:completionHandler: z klasy klasy NSExtensionContext. Jak wskazano strzałkami odczytu/zapisu w Rys. 2-3, każde rozszerzenie aplikacji i jej aplikacja zawierająca mogą uzyskać dostęp do udostępnionych danych w prywatnym kontenerze. Pełny słownik komunikacji między rozszerzeniem, aplikacją hosta i jego aplikacją zawierającą aplikację jest przedstawiony w prostej postaci na rysunku 2-3.

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

+0

nie dostaniesz punktu 3 i 4. możesz wyjaśnić więcej i prawidłowo. –

+0

to otworzy twoją aplikację, sprawdź 6 pkt .. ale mówisz bez otwierania aplikacji, myślę, że to nie jest możliwe, sprawdź dokumentację. – karthikeyan