
App-Erweiterungen wurden in iOS 8 veröffentlicht und machten das System für Benutzer flexibler, leistungsfähiger und erschwinglicher. Anwendungen können als Widget im Benachrichtigungscenter angezeigt werden, bieten ihre Filter für Fotos in Fotos an, zeigen eine neue Systemtastatur an und vieles mehr. Gleichzeitig wurde die Sicherheit der Benutzerdaten und des Systems gewahrt. Die Funktionen der Arbeit von App Extensions werden unten erläutert.
Apple hat immer versucht, Anwendungen sorgfältig voneinander zu isolieren. Dies ist der beste Weg, um die Sicherheit der Benutzer zu gewährleisten und ihre Daten zu schützen. Jede Anwendung erhält einen separaten Platz im Dateisystem mit eingeschränktem Zugriff. App-Erweiterungen ermöglichten die Interaktion mit der Anwendung, ohne sie zu starten oder auf dem Bildschirm anzuzeigen. Somit steht ein Teil seiner Funktionalität Benutzern zur Verfügung, wenn sie mit anderen Anwendungen oder dem System interagieren.
App-Erweiterungen sind ausführbare Dateien, die unabhängig von der enthaltenen Anwendung ausgeführt werden -
Enthält App . Sie können nicht allein mit der enthaltenen App im App Store veröffentlicht werden. Alle App-Erweiterungen führen eine bestimmte Aufgabe aus und sind je nach Typ nur an einen Bereich von iOS gebunden. Beispiel: Benutzerdefinierte Tastaturerweiterungen dienen zum Ersetzen der Standardtastatur und Fotobearbeitungserweiterungen zum Bearbeiten von Fotos in Fotos. Derzeit gibt es
25 Arten von App-Erweiterungen.
Life Extension App Extension
Die Anwendung, mit der der Benutzer die App-Erweiterung startet, wird als
Host-App bezeichnet . Die Host-App startet den Lebenszyklus der App-Erweiterung und sendet eine Anfrage als Antwort auf eine Benutzeraktion:

- Der Benutzer wählt die App-Erweiterung über die Host-App aus.
- Die Host-App sendet eine App-Erweiterungsanforderung.
- iOS startet die App-Erweiterung im Kontext der Host-App und richtet einen Kommunikationskanal zwischen ihnen ein.
- Der Benutzer führt eine Aktion in der App-Erweiterung aus.
- Die App-Erweiterung schließt die Anforderung von der Host-App ab, führt eine Aufgabe aus oder startet einen Hintergrundprozess, um sie abzuschließen. Nach Abschluss der Aufgabe kann das Ergebnis an die Host-App zurückgegeben werden.
- Sobald die App-Erweiterung ihren Code ausführt, beendet das System diese App-Erweiterung.
Wenn Sie beispielsweise ein Foto von Fotos mit der Facebook-Freigabeerweiterung freigeben, ist Facebook die enthaltende App und Fotos die Host-App. In diesem Fall startet Fotos den Lebenszyklus der Facebook-Freigabeerweiterung, wenn der Benutzer ihn im Freigabemenü auswählt:

Interaktion mit der App-Erweiterung

- Enthält App - Host App
Interagiere nicht miteinander.
- App-Erweiterung - Host-App
Interagiere mit IPC .
- App-Erweiterung - Enthält App
Indirekte Interaktion. App-Gruppen werden für den Datenaustausch verwendet, und Embedded Frameworks werden für allgemeinen Code verwendet. Sie können die enthaltende App über die App-Erweiterung mithilfe der URL-Schemata starten.
Generischer Code: dynamische Frameworks
Wenn die enthaltende App und die App-Erweiterung denselben Code verwenden, sollte dieser in einem dynamischen Framework platziert werden.
Beispielsweise kann eine Fotobearbeitungserweiterung einer benutzerdefinierten Fotobearbeitungsanwendung zugeordnet sein, die einige Filter aus der enthaltenen App verwendet. Eine gute Lösung wäre, ein dynamisches Framework für diese Filter zu erstellen.
Fügen Sie dazu ein neues
Ziel hinzu und wählen Sie das
Cocoa Touch Framework aus :

Geben Sie einen Namen an (z. B.
ImageFilters ), und im Navigatorfenster wird ein neuer Ordner mit dem Namen des erstellten Frameworks angezeigt:

Sie müssen sicherstellen, dass das Framework keine APIs verwendet, die für App-Erweiterungen nicht verfügbar sind:
- Geteilt von UIApplication.
- Mit Unzugänglichkeitsmakros gekennzeichnete APIs.
- Kamera und Mikrofon (außer iMessage Extension).
- Ausführen langwieriger Hintergrundaufgaben (Funktionen dieser Einschränkung variieren je nach Art der App-Erweiterung).
- Daten mit AirDrop empfangen.
Die Verwendung einer dieser Listen in App-Erweiterungen führt zu deren Ablehnung, wenn sie im App Store veröffentlicht werden.
In den Framework-Einstellungen unter
Allgemein müssen Sie das Kontrollkästchen neben
"Nur App-Erweiterungs-API zulassen" aktivieren :

Im Framework-Code müssen alle Klassen, Methoden und Eigenschaften, die in der Containing App und den App Extensions verwendet werden,
public
. Wo immer Sie das Framework verwenden müssen,
import
:
import ImageFilters
Datenaustausch: App-Gruppen
Die Containing App und die App Extension haben ihre eigenen begrenzten Abschnitte des Dateisystems und nur sie haben Zugriff darauf. Damit die enthaltende App und die App-Erweiterung einen gemeinsamen Container mit Lese- und Schreibzugriff haben, müssen Sie eine App-Gruppe für sie erstellen.
Die App-Gruppe wird im
Apple Developer Portal erstellt :

Klicken Sie in der oberen rechten Ecke auf "+". Geben Sie im angezeigten Fenster die erforderlichen Daten ein:

Weiter
Weiter -> Registrieren -> Fertig .
Wechseln Sie in den Einstellungen der enthaltenen App zur Registerkarte Funktionen, aktivieren Sie App-Gruppen und wählen Sie die erstellte Gruppe aus:

Ähnliches gilt für die App-Erweiterung:

Jetzt teilen sich die Containing App und die App Extension einen Container. Als nächstes werden wir darüber sprechen, wie man es liest und schreibt.
UserDefaults
Um eine kleine Datenmenge auszutauschen, ist es praktisch,
UserDefaults
zu verwenden. Sie müssen lediglich den Namen der App-Gruppe angeben:
let sharedDefaults = UserDefaults(suiteName: "group.com.maxial.onemoreapp")
NSFileCoordinator und NSFilePresenter
Für Big Data ist
NSFileCoordinator
besser geeignet, um die Lese- / Schreibkonsistenz sicherzustellen. Dadurch wird eine Beschädigung der Daten vermieden, da möglicherweise mehrere Prozesse gleichzeitig darauf zugreifen können.
Die URL des freigegebenen Containers wird wie folgt abgerufen:
let sharedUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.maxial.onemoreapp")
Aufzeichnung:
fileCoordinator.coordinate(writingItemAt: sharedUrl, options: [], error: nil) { [unowned self] newUrl in do { let data = try NSKeyedArchiver.archivedData(withRootObject: self.object, requiringSecureCoding: false) try data.write(to: newUrl, options: .atomic) } catch { print(error) } }
Lesen:
fileCoordinator.coordinate(readingItemAt: sharedUrl, options: [], error: nil) { newUrl in do { let data = try Data(contentsOf: newUrl) if let object = try NSKeyedUnarchiver.unarchivedObject(ofClass: NSString.self, from: data) as String? { self.object = object } } catch { print(error) } }
Es ist zu beachten, dass
NSFileCoordinator
synchron arbeitet. Während einige Dateien von einem Prozess belegt werden, müssen andere warten, bis sie freigegeben werden.
Wenn die App-Erweiterung wissen soll, wann die Containing App den Datenstatus ändert, wird
NSFilePresenter
verwendet. Dies ist ein Protokoll, dessen Implementierung folgendermaßen aussehen kann:
extension TodayViewController: NSFilePresenter { var presentedItemURL: URL? { let sharedUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.maxial.onemoreapp") return sharedUrl?.appendingPathComponent("Items") } var presentedItemOperationQueue: OperationQueue { return .main } func presentedItemDidChange() { } }
Die Eigenschaft presentItemOperationQueue gibt eine Warteschlange zurück, die für Rückrufe beim Ändern von Dateien verwendet wird. Die Methode
presentedItemDidChange()
wird aufgerufen, wenn ein Prozess, in diesem Fall die Containing App, den Inhalt der Daten ändert. Wenn Änderungen direkt mithilfe von Schreibaufrufen auf niedriger Ebene vorgenommen wurden, wird
presentedItemDidChange()
nicht aufgerufen. Es werden nur Änderungen gezählt, die den
NSFileCoordinator
.
Beim Initialisieren eines
NSFileCoordinator
Objekts
NSFileCoordinator
empfohlen, das
NSFilePresenter
Objekt zu übergeben, insbesondere wenn eine Dateioperation
NSFilePresenter
:
let fileCoordinator = NSFileCoordinator(filePresenter: self)
Andernfalls erhält das
NSFilePresenter
Objekt Benachrichtigungen über diese Vorgänge, die zu Deadlocks führen können, wenn Sie im selben Thread arbeiten.
Um den Status der Daten zu überwachen, müssen Sie die Methode
addFilePresenter(_:)
mit dem entsprechenden Objekt aufrufen:
NSFileCoordinator.addFilePresenter(self)
Alle später erstellten
NSFileCoordinator
Objekte kennen dieses
NSFilePresenter
Objekt automatisch und benachrichtigen über Änderungen in seinem Verzeichnis.
Verwenden Sie
removeFilePresenter(_:)
um die Überwachung des Datenstatus zu
removeFilePresenter(_:)
:
NSFileCoordinator.removeFilePresenter(self)
Kerndaten
Für die gemeinsame Nutzung von Daten können Sie SQLite und entsprechend Core Data verwenden. Sie können Prozesse verwalten, die mit gemeinsam genutzten Daten arbeiten. Um Core Data für die gemeinsame
NSPersistentContainer
zwischen der Containing App und der App Extension zu konfigurieren, erstellen Sie eine Unterklasse von
NSPersistentContainer
und überschreiben Sie die
defaultDirectoryURL
Methode, die die Datenspeicheradresse zurückgeben soll:
class SharedPersistentContainer: NSPersistentContainer { override open class func defaultDirectoryURL() -> URL { var storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.maxial.onemoreapp") storeURL = storeURL?.appendingPathComponent("OneMoreApp.sqlite") return storeURL! } }
AppDelegate
in
AppDelegate
die Eigenschaft
persistentContainer
. Es wird automatisch erstellt, wenn beim Erstellen eines Projekts das Kontrollkästchen
Kerndaten verwenden aktiviert ist. Jetzt geben wir ein Objekt der
SharedPersistentContainer
Klasse zurück:
lazy var persistentContainer: NSPersistentContainer = { let container = SharedPersistentContainer(name: "OneMoreApp") container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } }) return container }()
Sie müssen
lediglich .xcdatamodeld zur App-Erweiterung hinzufügen. Wählen Sie im Navigatorbereich die Datei .xcdatamodeld aus.
Aktivieren Sie im Dateiinspektor im Abschnitt Zielmitgliedschaft das Kontrollkästchen neben App-Erweiterung:

Somit können die enthaltende App und die App-Erweiterung Daten in denselben Speicher lesen und schreiben und dasselbe Modell verwenden.
Starten der enthaltenen App über die App-Erweiterung
Wenn die Host-App eine App-Erweiterungsanforderung sendet, stellt sie einen
extensionContext
bereit. Dieses Objekt verfügt über eine
open(_:completionHandler:)
-Methode, mit der Sie die Containing App öffnen können. Diese Methode ist jedoch nicht für alle Arten von App-Erweiterungen verfügbar. Unter iOS wird es von Today Extension und iMessage Extension unterstützt. iMessage Extension kann damit nur die Containing App öffnen. Wenn die Today Extension eine andere Anwendung damit öffnet, ist möglicherweise eine zusätzliche Überprüfung erforderlich, um sie an den App Store zu senden.
Um die Anwendung über die App-Erweiterung zu öffnen, müssen Sie das URL-Schema in der enthaltenen App definieren:

Rufen Sie als Nächstes die Methode
open(_:completionHandler:)
mit diesem Diagramm aus der App-Erweiterung auf:
guard let url = URL(string: "OneMoreAppUrl://") else { return } extensionContext?.open(url, completionHandler: nil)
Für die Arten von App-Erweiterungen, die die Methode
open(_:completionHandler:)
aufrufen, gibt es auch eine Möglichkeit. Es besteht jedoch die Möglichkeit, dass die Anwendung beim Einchecken im App Store abgelehnt wird. Das Wesentliche der Methode besteht darin
UIResponder
die Kette der
UIResponder
Objekte zu
UIResponder
, bis eine
UIApplication
UIResponder
vorhanden ist, die den
openURL
Aufruf akzeptiert:
guard let url = URL(string: "OneMoreAppUrl://") else { return } let selectorOpenURL = sel_registerName("openURL:") var responder: UIResponder? = self while responder != nil { if responder?.responds(to: selectorOpenURL) == true { responder?.perform(selectorOpenURL, with: url) } responder = responder?.next }
Zukünftige App-Erweiterungen
App Extensions hat viel zur iOS-Entwicklung beigetragen. Allmählich erscheinen mehr Arten von App-Erweiterungen, deren Funktionen sich weiterentwickeln. Mit der Veröffentlichung des iOS 12 SDK können Sie jetzt beispielsweise mit dem Inhaltsbereich in Benachrichtigungen interagieren, der so lange fehlte.
Daher entwickelt Apple dieses Tool weiter, was Optimismus in Bezug auf seine Zukunft hervorruft.
Nützliche Links:Offizielle DokumentationDaten zwischen iOS-Apps und App-Erweiterungen austauschenTipps zur Entwicklung von iOS 8-App-Erweiterungen