Freigeben über


Dokumentauswahl in Xamarin.iOS

Mit der Dokumentauswahl können Dokumente zwischen Apps freigegeben werden. Diese Dokumente können in iCloud oder im Verzeichnis einer anderen App gespeichert werden. Dokumente werden über die Gruppe von Dokumentanbietererweiterungen freigegeben, die Benutzer*innen auf dem Gerät installiert haben.

Aufgrund der Schwierigkeiten beim Synchronisieren von Dokumenten über Apps und die Cloud hinweg führen sie eine gewisse Komplexität ein.

Anforderungen

Die folgenden Schritte sind erforderlich, um die in diesem Artikel beschriebenen Schritte auszuführen:

  • Xcode 7 und iOS 8 oder höher – Apples Xcode 7 und iOS 8 oder neuere APIs müssen auf dem Computer des Entwicklers installiert und konfiguriert werden.
  • Visual Studio oder Visual Studio für Mac – Die neueste Version von Visual Studio für Mac sollte installiert werden.
  • iOS-Gerät – Ein iOS-Gerät mit iOS 8 oder höher.

Änderungen an iCloud

Um die neuen Features der Dokumentauswahl zu implementieren, wurden die folgenden Änderungen am iCloud-Dienst von Apple vorgenommen:

  • Der iCloud Daemon wurde vollständig mit CloudKit umgeschrieben.
  • Die vorhandenen iCloud-Features wurden in iCloud Drive umbenannt.
  • Unterstützung für Das Microsoft Windows-Betriebssystem wurde zu iCloud hinzugefügt.
  • Ein iCloud-Ordner wurde im Mac OS Finder hinzugefügt.
  • iOS-Geräte können auf den Inhalt des Mac OS iCloud-Ordners zugreifen.

Wichtig

Apple stellt Tools zur Verfügung, die Entwickler dabei unterstützen, die Datenschutz-Grundverordnung (DSGVO) der Europäischen Union umzusetzen.

Was ist ein Dokument?

Wenn Sie auf ein Dokument in iCloud verweisen, handelt es sich um eine einzelne, eigenständige Entität und sollte vom Benutzer als solche wahrgenommen werden. Ein Benutzer möchte das Dokument möglicherweise ändern oder für andere Benutzer freigeben (z. B. per E-Mail).

Es gibt mehrere Dateitypen, die der Benutzer sofort als Dokumente erkennt, z. B. Seiten, Keynote- oder Zahlendateien. iCloud ist jedoch nicht auf dieses Konzept beschränkt. Beispielsweise kann der Zustand eines Spiels (z. B. ein Schachspiel) als Dokument behandelt und in iCloud gespeichert werden. Diese Datei kann zwischen den Geräten eines Benutzers übergeben werden und es ihnen ermöglichen, ein Spiel aufzunehmen, bei dem sie auf einem anderen Gerät aufgehört haben.

Umgang mit Dokumenten

Bevor Sie sich mit dem Code befassen, der für die Verwendung der Dokumentauswahl mit Xamarin erforderlich ist, behandelt dieser Artikel die bewährten Methoden für die Arbeit mit iCloud-Dokumenten und einige der Änderungen, die an vorhandenen APIs vorgenommen wurden, die zur Unterstützung der Dokumentauswahl erforderlich sind.

Verwenden der Dateikoordination

Da eine Datei von mehreren verschiedenen Speicherorten geändert werden kann, muss die Koordination verwendet werden, um Datenverluste zu verhindern.

Verwenden der Dateikoordination

Sehen wir uns die obige Abbildung an:

  1. Ein iOS-Gerät mit Dateikoordination erstellt ein neues Dokument und speichert es im iCloud-Ordner.
  2. iCloud speichert die geänderte Datei für die Verteilung auf jedes Gerät in der Cloud.
  3. Ein angefügter Mac sieht die geänderte Datei im iCloud-Ordner und verwendet die Dateikoordination, um die Änderungen in die Datei zu kopieren.
  4. Ein Gerät, das die Dateikoordination nicht verwendet, nimmt eine Änderung an der Datei vor und speichert sie im iCloud-Ordner. Diese Änderungen werden sofort auf die anderen Geräte repliziert.

Gehen Sie davon aus, dass das ursprüngliche iOS-Gerät oder der Mac die Datei bearbeitet hat. Jetzt gehen ihre Änderungen verloren und werden mit der Version der Datei vom nicht koordinierten Gerät überschrieben. Um Datenverluste zu verhindern, ist die Dateikoordination ein Muss beim Arbeiten mit cloudbasierten Dokumenten.

Verwenden von UIDocument

UIDocument macht Dinge einfach (oder NSDocument unter macOS), indem sie das gesamte schwere Hebeheben für den Entwickler ausführen. Es bietet integrierte Dateikoordination mit Hintergrundwarteschlangen, um die Benutzeroberfläche der Anwendung zu blockieren.

UIDocument macht mehrere allgemeine APIs verfügbar, die den Entwicklungsaufwand einer Xamarin-Anwendung für jeden Zweck vereinfachen, den der Entwickler benötigt.

Der folgende Code erstellt eine Unterklasse zum UIDocument Implementieren eines generischen textbasierten Dokuments, das zum Speichern und Abrufen von Text aus iCloud verwendet werden kann:

using System;
using Foundation;
using UIKit;

namespace DocPicker
{
    public class GenericTextDocument : UIDocument
    {
        #region Private Variable Storage
        private NSString _dataModel;
        #endregion

        #region Computed Properties
        public string Contents {
            get { return _dataModel.ToString (); }
            set { _dataModel = new NSString(value); }
        }
        #endregion

        #region Constructors
        public GenericTextDocument (NSUrl url) : base (url)
        {
            // Set the default document text
            this.Contents = "";
        }

        public GenericTextDocument (NSUrl url, string contents) : base (url)
        {
            // Set the default document text
            this.Contents = contents;
        }
        #endregion

        #region Override Methods
        public override bool LoadFromContents (NSObject contents, string typeName, out NSError outError)
        {
            // Clear the error state
            outError = null;

            // Were any contents passed to the document?
            if (contents != null) {
                _dataModel = NSString.FromData( (NSData)contents, NSStringEncoding.UTF8 );
            }

            // Inform caller that the document has been modified
            RaiseDocumentModified (this);

            // Return success
            return true;
        }

        public override NSObject ContentsForType (string typeName, out NSError outError)
        {
            // Clear the error state
            outError = null;

            // Convert the contents to a NSData object and return it
            NSData docData = _dataModel.Encode(NSStringEncoding.UTF8);
            return docData;
        }
        #endregion

        #region Events
        public delegate void DocumentModifiedDelegate(GenericTextDocument document);
        public event DocumentModifiedDelegate DocumentModified;

        internal void RaiseDocumentModified(GenericTextDocument document) {
            // Inform caller
            if (this.DocumentModified != null) {
                this.DocumentModified (document);
            }
        }
        #endregion
    }
}

Die GenericTextDocument oben beschriebene Klasse wird in diesem Artikel verwendet, wenn Sie mit der Dokumentauswahl und externen Dokumenten in einer Xamarin.iOS 8-Anwendung arbeiten.

Asynchrone Dateikoordination

iOS 8 bietet mehrere neue asynchrone Dateikoordinationsfunktionen über die neuen Dateikoordinations-APIs. Vor iOS 8 waren alle vorhandenen Dateikoordinations-APIs völlig synchron. Dies bedeutete, dass der Entwickler für die Implementierung einer eigenen Hintergrundwarteschlange verantwortlich war, um zu verhindern, dass die Dateikoordination die Benutzeroberfläche der Anwendung blockiert.

Die neue NSFileAccessIntent Klasse enthält eine URL, die auf die Datei verweist, und mehrere Optionen zum Steuern des erforderlichen Koordinationstyps. Der folgende Code veranschaulicht das Verschieben einer Datei von einem Speicherort zu einem anderen mithilfe von Absichten:

// Get source options
var srcURL = NSUrl.FromFilename ("FromFile.txt");
var srcIntent = NSFileAccessIntent.CreateReadingIntent (srcURL, NSFileCoordinatorReadingOptions.ForUploading);

// Get destination options
var dstURL = NSUrl.FromFilename ("ToFile.txt");
var dstIntent = NSFileAccessIntent.CreateReadingIntent (dstURL, NSFileCoordinatorReadingOptions.ForUploading);

// Create an array
var intents = new NSFileAccessIntent[] {
    srcIntent,
    dstIntent
};

// Initialize a file coordination with intents
var queue = new NSOperationQueue ();
var fileCoordinator = new NSFileCoordinator ();
fileCoordinator.CoordinateAccess (intents, queue, (err) => {
    // Was there an error?
    if (err!=null) {
        Console.WriteLine("Error: {0}",err.LocalizedDescription);
    }
});

Suchen und Auflisten von Dokumenten

Die Möglichkeit zum Ermitteln und Auflisten von Dokumenten ist die Verwendung der vorhandenen NSMetadataQuery APIs. In diesem Abschnitt werden neue Features behandelt, die NSMetadataQuery das Arbeiten mit Dokumenten noch einfacher machen als zuvor.

Vorhandenes Verhalten

Vor iOS 8 war es langsam, NSMetadataQuery lokale Dateiänderungen wie: Löschvorgänge, Erstellungen und Umbenennungen zu übernehmen.

Übersicht über lokale NSMetadataQuery-Dateiänderungen

Für dieses Diagramm gilt:

  1. Für Dateien, die bereits im Anwendungscontainer vorhanden sind, sind bereits NSMetadata vorhandene Datensätze vorhanden, NSMetadataQuery die bereits erstellt und gepoolt wurden, damit sie sofort für die Anwendung verfügbar sind.
  2. Die Anwendung erstellt eine neue Datei im Anwendungscontainer.
  3. Es gibt eine Verzögerung, bevor NSMetadataQuery die Änderung des Anwendungscontainers angezeigt wird und der erforderliche NSMetadata Datensatz erstellt wird.

Aufgrund der Verzögerung beim Erstellen des NSMetadata Datensatzes musste die Anwendung zwei Datenquellen geöffnet haben: eine für lokale Dateiänderungen und eine für cloudbasierte Änderungen.

Nähte

In iOS 8 NSMetadataQuery ist die direkte Verwendung mit einem neuen Feature namens "Stitching" einfacher:

NSMetadataQuery mit einem neuen Feature namens

Verwenden von Stichen im obigen Diagramm:

  1. Wie zuvor, für Dateien, die bereits im Anwendungscontainer vorhanden sind, NSMetadataQuery wurden bereits NSMetadata vorhandene Datensätze vorgefertigt und gepoolt.
  2. Die Anwendung erstellt eine neue Datei im Anwendungscontainer mithilfe der Dateikoordination.
  3. Ein Hook im Anwendungscontainer sieht die Änderung und Aufrufe NSMetadataQuery zum Erstellen des erforderlichen NSMetadata Datensatzes.
  4. Der NSMetadata Datensatz wird direkt nach der Datei erstellt und der Anwendung zur Verfügung gestellt.

Durch Die Verwendung von Stitching muss die Anwendung keine Datenquelle mehr öffnen, um lokale und cloudbasierte Dateiänderungen zu überwachen. Jetzt kann sich die Anwendung direkt darauf NSMetadataQuery verlassen.

Wichtig

Das Heften funktioniert nur, wenn die Anwendung die Dateikoordination verwendet, wie im abschnitt oben dargestellt. Wenn die Dateikoordination nicht verwendet wird, werden die APIs standardmäßig auf das vorhandene Vor-iOS 8-Verhalten angewendet.

Neue iOS 8-Metadatenfeatures

Die folgenden neuen Features wurden in iOS 8 hinzugefügt NSMetadataQuery :

  • NSMetatadataQuery kann jetzt nicht lokale Dokumente auflisten, die in der Cloud gespeichert sind.
  • Neue APIs wurden hinzugefügt, um auf Metadateninformationen zu den cloudbasierten Dokumenten zuzugreifen.
  • Es gibt eine neue NSUrl_PromisedItems API, die auf die Dateiattribute von Dateien zugreift, die möglicherweise lokal verfügbar sind oder nicht.
  • Verwenden Sie die GetPromisedItemResourceValue Methode, um Informationen zu einer bestimmten Datei abzurufen, oder verwenden Sie die GetPromisedItemResourceValues Methode, um Informationen zu mehreren Dateien gleichzeitig abzurufen.

Für den Umgang mit Metadaten wurden zwei neue Dateikoordinationskennzeichnungen hinzugefügt:

  • NSFileCoordinatorReadImmediatelyAvailableMetadataOnly
  • NSFileCoordinatorWriteContentIndependentMetadataOnly

Mit den obigen Kennzeichnungen muss der Inhalt der Dokumentdatei nicht lokal verfügbar sein, damit sie verwendet werden können.

Im folgenden Codesegment wird gezeigt, wie NSMetadataQuery Sie das Vorhandensein einer bestimmten Datei abfragen und die Datei erstellen, wenn sie nicht vorhanden ist:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Foundation;
using UIKit;
using ObjCRuntime;
using System.IO;

#region Static Properties
public const string TestFilename = "test.txt";
#endregion

#region Computed Properties
public bool HasiCloud { get; set; }
public bool CheckingForiCloud { get; set; }
public NSUrl iCloudUrl { get; set; }

public GenericTextDocument Document { get; set; }
public NSMetadataQuery Query { get; set; }
#endregion

#region Private Methods
private void FindDocument () {
    Console.WriteLine ("Finding Document...");

    // Create a new query and set it's scope
    Query = new NSMetadataQuery();
    Query.SearchScopes = new NSObject [] {
                NSMetadataQuery.UbiquitousDocumentsScope,
                NSMetadataQuery.UbiquitousDataScope,
                NSMetadataQuery.AccessibleUbiquitousExternalDocumentsScope
            };

    // Build a predicate to locate the file by name and attach it to the query
    var pred = NSPredicate.FromFormat ("%K == %@"
        , new NSObject[] {
            NSMetadataQuery.ItemFSNameKey
            , new NSString(TestFilename)});
    Query.Predicate = pred;

    // Register a notification for when the query returns
    NSNotificationCenter.DefaultCenter.AddObserver (this,
            new Selector("queryDidFinishGathering:"),             NSMetadataQuery.DidFinishGatheringNotification,
            Query);

    // Start looking for the file
    Query.StartQuery ();
    Console.WriteLine ("Querying: {0}", Query.IsGathering);
}

[Export("queryDidFinishGathering:")]
public void DidFinishGathering (NSNotification notification) {
    Console.WriteLine ("Finish Gathering Documents.");

    // Access the query and stop it from running
    var query = (NSMetadataQuery)notification.Object;
    query.DisableUpdates();
    query.StopQuery();

    // Release the notification
    NSNotificationCenter.DefaultCenter.RemoveObserver (this
        , NSMetadataQuery.DidFinishGatheringNotification
        , query);

    // Load the document that the query returned
    LoadDocument(query);
}

private void LoadDocument (NSMetadataQuery query) {
    Console.WriteLine ("Loading Document...");    

    // Take action based on the returned record count
    switch (query.ResultCount) {
    case 0:
        // Create a new document
        CreateNewDocument ();
        break;
    case 1:
        // Gain access to the url and create a new document from
        // that instance
        NSMetadataItem item = (NSMetadataItem)query.ResultAtIndex (0);
        var url = (NSUrl)item.ValueForAttribute (NSMetadataQuery.ItemURLKey);

        // Load the document
        OpenDocument (url);
        break;
    default:
        // There has been an issue
        Console.WriteLine ("Issue: More than one document found...");
        break;
    }
}
#endregion

#region Public Methods
public void OpenDocument(NSUrl url) {

    Console.WriteLine ("Attempting to open: {0}", url);
    Document = new GenericTextDocument (url);

    // Open the document
    Document.Open ( (success) => {
        if (success) {
            Console.WriteLine ("Document Opened");
        } else
            Console.WriteLine ("Failed to Open Document");
    });

    // Inform caller
    RaiseDocumentLoaded (Document);
}

public void CreateNewDocument() {
    // Create path to new file
    // var docsFolder = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
    var docsFolder = Path.Combine(iCloudUrl.Path, "Documents");
    var docPath = Path.Combine (docsFolder, TestFilename);
    var ubiq = new NSUrl (docPath, false);

    // Create new document at path
    Console.WriteLine ("Creating Document at:" + ubiq.AbsoluteString);
    Document = new GenericTextDocument (ubiq);

    // Set the default value
    Document.Contents = "(default value)";

    // Save document to path
    Document.Save (Document.FileUrl, UIDocumentSaveOperation.ForCreating, (saveSuccess) => {
        Console.WriteLine ("Save completion:" + saveSuccess);
        if (saveSuccess) {
            Console.WriteLine ("Document Saved");
        } else {
            Console.WriteLine ("Unable to Save Document");
        }
    });

    // Inform caller
    RaiseDocumentLoaded (Document);
}

public bool SaveDocument() {
    bool successful = false;

    // Save document to path
    Document.Save (Document.FileUrl, UIDocumentSaveOperation.ForOverwriting, (saveSuccess) => {
        Console.WriteLine ("Save completion: " + saveSuccess);
        if (saveSuccess) {
            Console.WriteLine ("Document Saved");
            successful = true;
        } else {
            Console.WriteLine ("Unable to Save Document");
            successful=false;
        }
    });

    // Return results
    return successful;
}
#endregion

#region Events
public delegate void DocumentLoadedDelegate(GenericTextDocument document);
public event DocumentLoadedDelegate DocumentLoaded;

internal void RaiseDocumentLoaded(GenericTextDocument document) {
    // Inform caller
    if (this.DocumentLoaded != null) {
        this.DocumentLoaded (document);
    }
}
#endregion

Dokumentminiaturansichten

Apple fühlt, dass die beste Benutzererfahrung beim Auflisten von Dokumenten für eine Anwendung die Verwendung von Vorschauen ist. Dadurch erhalten Endbenutzer Kontext, sodass sie das Dokument, mit dem sie arbeiten möchten, schnell identifizieren können.

Vor iOS 8 erforderte die Anzeige von Dokumentvorschauen eine benutzerdefinierte Implementierung. Neu bei iOS 8 sind Dateisystemattribute, mit denen entwickler schnell mit Dokumentminiaturansichten arbeiten können.

Abrufen von Dokumentminiaturansichten

Durch Aufrufen der GetPromisedItemResourceValue Methoden oder GetPromisedItemResourceValues Methoden NSUrl_PromisedItems API wird ein NSUrlThumbnailDictionary, zurückgegeben. Der einzige Schlüssel, der derzeit in diesem Wörterbuch enthalten ist, ist der NSThumbnial1024X1024SizeKey entsprechende Schlüssel UIImage.

Speichern von Dokumentminiaturansichten

Die einfachste Möglichkeit zum Speichern einer Miniaturansicht ist die Verwendung UIDocument. Durch Aufrufen der GetFileAttributesToWrite Methode und UIDocument Festlegen der Miniaturansicht wird sie automatisch gespeichert, wenn die Dokumentdatei ist. Der iCloud-Daemon wird diese Änderung sehen und an iCloud weitergeben. Auf Mac OS X werden Miniaturansichten automatisch für den Entwickler durch das Quick Look-Plug-In generiert.

Mit den Grundlagen der direkten Arbeit mit iCloud-basierten Dokumenten sowie den Änderungen an der vorhandenen API sind wir bereit, den Dokumentauswahl-Ansichtscontroller in einer mobilen Xamarin iOS 8-Anwendung zu implementieren.

Aktivieren von iCloud in Xamarin

Bevor die Dokumentauswahl in einer Xamarin.iOS-Anwendung verwendet werden kann, muss die iCloud-Unterstützung sowohl in Ihrer Anwendung als auch über Apple aktiviert werden.

In den folgenden Schritten wird der Bereitstellungsprozess für iCloud beschrieben.

  1. Erstellen Sie einen iCloud-Container.
  2. Erstellen Sie eine App-ID, die den iCloud-App-Dienst enthält.
  3. Erstellen Sie ein Bereitstellungsprofil, das diese App-ID enthält.

Der Leitfaden zum Arbeiten mit Funktionen führt sie durch die ersten beiden Schritte. Führen Sie zum Erstellen eines Bereitstellungsprofils die Schritte im Bereitstellungsprofilhandbuch aus.

Die folgenden Schritte führen Sie durch, wie Sie Ihre Anwendung für iCloud konfigurieren:

Gehen Sie folgendermaßen vor:

  1. Öffnen Sie das Projekt in Visual Studio für Mac oder Visual Studio.

  2. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie "Optionen" aus.

  3. Wählen Sie im Dialogfeld "Optionen" die iOS-Anwendung aus, um sicherzustellen, dass der Bündelbezeichner mit dem bezeichner übereinstimmt, der in der oben für die Anwendung erstellten App-ID definiert wurde.

  4. Wählen Sie "iOS Bundle Signing" aus, wählen Sie die Entwickleridentität und das oben erstellte Bereitstellungsprofil aus.

  5. Klicken Sie auf die Schaltfläche "OK ", um die Änderungen zu speichern und das Dialogfeld zu schließen.

  6. Klicken Sie mit der rechten Maustaste Entitlements.plist auf die Projektmappen-Explorer, um sie im Editor zu öffnen.

    Wichtig

    In Visual Studio müssen Sie möglicherweise den Berechtigungs-Editor öffnen, indem Sie mit der rechten Maustaste darauf klicken, "Öffnen mit" und dann den Eigenschaftenlisten-Editor auswählen.

  7. Aktivieren Sie iCloud , iCloud-Dokumente , Key-Value-Speicher und CloudKit .

  8. Stellen Sie sicher, dass der Container für die Anwendung vorhanden ist (wie oben erstellt). Beispiel: iCloud.com.your-company.AppName

  9. Speichern Sie die Änderungen in der Datei.

Weitere Informationen zu Berechtigungen finden Sie im Leitfaden zum Arbeiten mit Berechtigungen .

Mit der oben genannten Einrichtung kann die Anwendung jetzt cloudbasierte Dokumente und den neuen Dokumentauswahl-Ansichtscontroller verwenden.

Allgemeiner Setupcode

Bevor Sie mit dem Dokumentauswahl-Ansichtscontroller beginnen, ist ein Standardsetupcode erforderlich. Beginnen Sie, indem Sie die Datei der Anwendung AppDelegate.cs ändern und wie folgt aussehen lassen:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Foundation;
using UIKit;
using ObjCRuntime;
using System.IO;

namespace DocPicker
{

    [Register ("AppDelegate")]
    public partial class AppDelegate : UIApplicationDelegate
    {
        #region Static Properties
        public const string TestFilename = "test.txt";
        #endregion

        #region Computed Properties
        public override UIWindow Window { get; set; }
        public bool HasiCloud { get; set; }
        public bool CheckingForiCloud { get; set; }
        public NSUrl iCloudUrl { get; set; }

        public GenericTextDocument Document { get; set; }
        public NSMetadataQuery Query { get; set; }
        public NSData Bookmark { get; set; }
        #endregion

        #region Private Methods
        private void FindDocument () {
            Console.WriteLine ("Finding Document...");

            // Create a new query and set it's scope
            Query = new NSMetadataQuery();
            Query.SearchScopes = new NSObject [] {
                NSMetadataQuery.UbiquitousDocumentsScope,
                NSMetadataQuery.UbiquitousDataScope,
                NSMetadataQuery.AccessibleUbiquitousExternalDocumentsScope
            };

            // Build a predicate to locate the file by name and attach it to the query
            var pred = NSPredicate.FromFormat ("%K == %@",
                 new NSObject[] {NSMetadataQuery.ItemFSNameKey
                , new NSString(TestFilename)});
            Query.Predicate = pred;

            // Register a notification for when the query returns
            NSNotificationCenter.DefaultCenter.AddObserver (this
                , new Selector("queryDidFinishGathering:")
                , NSMetadataQuery.DidFinishGatheringNotification
                , Query);

            // Start looking for the file
            Query.StartQuery ();
            Console.WriteLine ("Querying: {0}", Query.IsGathering);
        }

        [Export("queryDidFinishGathering:")]
        public void DidFinishGathering (NSNotification notification) {
            Console.WriteLine ("Finish Gathering Documents.");

            // Access the query and stop it from running
            var query = (NSMetadataQuery)notification.Object;
            query.DisableUpdates();
            query.StopQuery();

            // Release the notification
            NSNotificationCenter.DefaultCenter.RemoveObserver (this
                , NSMetadataQuery.DidFinishGatheringNotification
                , query);

            // Load the document that the query returned
            LoadDocument(query);
        }

        private void LoadDocument (NSMetadataQuery query) {
            Console.WriteLine ("Loading Document...");    

            // Take action based on the returned record count
            switch (query.ResultCount) {
            case 0:
                // Create a new document
                CreateNewDocument ();
                break;
            case 1:
                // Gain access to the url and create a new document from
                // that instance
                NSMetadataItem item = (NSMetadataItem)query.ResultAtIndex (0);
                var url = (NSUrl)item.ValueForAttribute (NSMetadataQuery.ItemURLKey);

                // Load the document
                OpenDocument (url);
                break;
            default:
                // There has been an issue
                Console.WriteLine ("Issue: More than one document found...");
                break;
            }
        }
        #endregion

        #region Public Methods

        public void OpenDocument(NSUrl url) {

            Console.WriteLine ("Attempting to open: {0}", url);
            Document = new GenericTextDocument (url);

            // Open the document
            Document.Open ( (success) => {
                if (success) {
                    Console.WriteLine ("Document Opened");
                } else
                    Console.WriteLine ("Failed to Open Document");
            });

            // Inform caller
            RaiseDocumentLoaded (Document);
        }

        public void CreateNewDocument() {
            // Create path to new file
            // var docsFolder = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
            var docsFolder = Path.Combine(iCloudUrl.Path, "Documents");
            var docPath = Path.Combine (docsFolder, TestFilename);
            var ubiq = new NSUrl (docPath, false);

            // Create new document at path
            Console.WriteLine ("Creating Document at:" + ubiq.AbsoluteString);
            Document = new GenericTextDocument (ubiq);

            // Set the default value
            Document.Contents = "(default value)";

            // Save document to path
            Document.Save (Document.FileUrl, UIDocumentSaveOperation.ForCreating, (saveSuccess) => {
                Console.WriteLine ("Save completion:" + saveSuccess);
                if (saveSuccess) {
                    Console.WriteLine ("Document Saved");
                } else {
                    Console.WriteLine ("Unable to Save Document");
                }
            });

            // Inform caller
            RaiseDocumentLoaded (Document);
        }

        /// <summary>
        /// Saves the document.
        /// </summary>
        /// <returns><c>true</c>, if document was saved, <c>false</c> otherwise.</returns>
        public bool SaveDocument() {
            bool successful = false;

            // Save document to path
            Document.Save (Document.FileUrl, UIDocumentSaveOperation.ForOverwriting, (saveSuccess) => {
                Console.WriteLine ("Save completion: " + saveSuccess);
                if (saveSuccess) {
                    Console.WriteLine ("Document Saved");
                    successful = true;
                } else {
                    Console.WriteLine ("Unable to Save Document");
                    successful=false;
                }
            });

            // Return results
            return successful;
        }
        #endregion

        #region Override Methods
        public override void FinishedLaunching (UIApplication application)
        {

            // Start a new thread to check and see if the user has iCloud
            // enabled.
            new Thread(new ThreadStart(() => {
                // Inform caller that we are checking for iCloud
                CheckingForiCloud = true;

                // Checks to see if the user of this device has iCloud
                // enabled
                var uburl = NSFileManager.DefaultManager.GetUrlForUbiquityContainer(null);

                // Connected to iCloud?
                if (uburl == null)
                {
                    // No, inform caller
                    HasiCloud = false;
                    iCloudUrl =null;
                    Console.WriteLine("Unable to connect to iCloud");
                    InvokeOnMainThread(()=>{
                        var okAlertController = UIAlertController.Create ("iCloud Not Available", "Developer, please check your Entitlements.plist, Bundle ID and Provisioning Profiles.", UIAlertControllerStyle.Alert);
                        okAlertController.AddAction (UIAlertAction.Create ("Ok", UIAlertActionStyle.Default, null));
                        Window.RootViewController.PresentViewController (okAlertController, true, null);
                    });
                }
                else
                {    
                    // Yes, inform caller and save location the Application Container
                    HasiCloud = true;
                    iCloudUrl = uburl;
                    Console.WriteLine("Connected to iCloud");

                    // If we have made the connection with iCloud, start looking for documents
                    InvokeOnMainThread(()=>{
                        // Search for the default document
                        FindDocument ();
                    });
                }

                // Inform caller that we are no longer looking for iCloud
                CheckingForiCloud = false;

            })).Start();

        }

        // This method is invoked when the application is about to move from active to inactive state.
        // OpenGL applications should use this method to pause.
        public override void OnResignActivation (UIApplication application)
        {
        }

        // This method should be used to release shared resources and it should store the application state.
        // If your application supports background execution this method is called instead of WillTerminate
        // when the user quits.
        public override void DidEnterBackground (UIApplication application)
        {
            // Trap all errors
            try {
                // Values to include in the bookmark packet
                var resources = new string[] {
                    NSUrl.FileSecurityKey,
                    NSUrl.ContentModificationDateKey,
                    NSUrl.FileResourceIdentifierKey,
                    NSUrl.FileResourceTypeKey,
                    NSUrl.LocalizedNameKey
                };

                // Create the bookmark
                NSError err;
                Bookmark = Document.FileUrl.CreateBookmarkData (NSUrlBookmarkCreationOptions.WithSecurityScope, resources, iCloudUrl, out err);

                // Was there an error?
                if (err != null) {
                    // Yes, report it
                    Console.WriteLine ("Error Creating Bookmark: {0}", err.LocalizedDescription);
                }
            }
            catch (Exception e) {
                // Report error
                Console.WriteLine ("Error: {0}", e.Message);
            }
        }

        // This method is called as part of the transition from background to active state.
        public override void WillEnterForeground (UIApplication application)
        {
            // Is there any bookmark data?
            if (Bookmark != null) {
                // Trap all errors
                try {
                    // Yes, attempt to restore it
                    bool isBookmarkStale;
                    NSError err;
                    var srcUrl = new NSUrl (Bookmark, NSUrlBookmarkResolutionOptions.WithSecurityScope, iCloudUrl, out isBookmarkStale, out err);

                    // Was there an error?
                    if (err != null) {
                        // Yes, report it
                        Console.WriteLine ("Error Loading Bookmark: {0}", err.LocalizedDescription);
                    } else {
                        // Load document from bookmark
                        OpenDocument (srcUrl);
                    }
                }
                catch (Exception e) {
                    // Report error
                    Console.WriteLine ("Error: {0}", e.Message);
                }
            }

        }

        // This method is called when the application is about to terminate. Save data, if needed.
        public override void WillTerminate (UIApplication application)
        {
        }
        #endregion

        #region Events
        public delegate void DocumentLoadedDelegate(GenericTextDocument document);
        public event DocumentLoadedDelegate DocumentLoaded;

        internal void RaiseDocumentLoaded(GenericTextDocument document) {
            // Inform caller
            if (this.DocumentLoaded != null) {
                this.DocumentLoaded (document);
            }
        }
        #endregion
    }
}

Wichtig

Der obige Code enthält den Code aus dem Abschnitt "Entdecken und Auflisten von Dokumenten" oben. Es wird hier in seiner Gesamtheit dargestellt, wie es in einer tatsächlichen Anwendung erscheinen würde. Aus Gründen der Einfachheit funktioniert dieses Beispiel nur mit einer einzigen hartcodierten Datei (test.txt).

Der obige Code macht mehrere iCloud Drive-Tastenkombinationen verfügbar, damit sie im Rest der Anwendung einfacher arbeiten können.

Fügen Sie als Nächstes den folgenden Code zu einem beliebigen Ansichts- oder Ansichtscontainer hinzu, der die Dokumentauswahl verwendet oder mit cloudbasierten Dokumenten arbeitet:

using CloudKit;
...

#region Computed Properties
/// <summary>
/// Returns the delegate of the current running application
/// </summary>
/// <value>The this app.</value>
public AppDelegate ThisApp {
    get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
}
#endregion

Dadurch wird eine Verknüpfung hinzugefügt, um zu den AppDelegate oben erstellten iCloud-Verknüpfungen zu gelangen und darauf zuzugreifen.

In diesem Code sehen wir uns die Implementierung des Dokumentauswahl-Ansichtscontrollers in einer Xamarin iOS 8-Anwendung an.

Verwenden des Dokumentauswahl-Ansichtscontrollers

Vor iOS 8 war es sehr schwierig, von einer anderen Anwendung aus auf Dokumente zuzugreifen, da es keine Möglichkeit gab, Dokumente außerhalb der Anwendung innerhalb der App zu finden.

Vorhandenes Verhalten

Übersicht über vorhandenes Verhalten

Sehen wir uns den Zugriff auf ein externes Dokument vor iOS 8 an:

  1. Zuerst müsste der Benutzer die Anwendung öffnen, die ursprünglich das Dokument erstellt hat.
  2. Das Dokument ist ausgewählt und wird UIDocumentInteractionController verwendet, um das Dokument an die neue Anwendung zu senden.
  3. Schließlich wird eine Kopie des ursprünglichen Dokuments im Container der neuen Anwendung platziert.

Von dort aus steht das Dokument für die zweite Anwendung zum Öffnen und Bearbeiten zur Verfügung.

Ermitteln von Dokumenten außerhalb des Containers einer App

In iOS 8 kann eine Anwendung problemlos auf Dokumente außerhalb des eigenen Anwendungscontainers zugreifen:

Ermitteln von Dokumenten außerhalb des Containers einer App

Mithilfe der neuen iCloud-Dokumentauswahl ( UIDocumentPickerViewController) kann eine iOS-Anwendung direkt außerhalb des Anwendungscontainers suchen und darauf zugreifen. Dies UIDocumentPickerViewController stellt einen Mechanismus bereit, mit dem der Benutzer über Berechtigungen Zugriff auf ermittelte Dokumente gewähren und diese bearbeiten kann.

Eine Anwendung muss sich anmelden, damit ihre Dokumente in der iCloud-Dokumentauswahl angezeigt werden und für andere Anwendungen zur Verfügung stehen, um sie zu ermitteln und damit zu arbeiten. Damit eine Xamarin iOS 8-Anwendung ihren Anwendungscontainer gemeinsam verwendet, bearbeiten Sie sie Info.plist in einem Standardtext-Editor, und fügen Sie die folgenden beiden Zeilen am Ende des Wörterbuchs (zwischen den <dict>...</dict> Tags) hinzu:

<key>NSUbiquitousContainerIsDocumentScopePublic</key>
<true/>

Die UIDocumentPickerViewController Benutzeroberfläche bietet eine großartige neue Benutzeroberfläche, mit der der Benutzer Dokumente auswählen kann. Gehen Sie wie folgt vor, um den Dokumentauswahl-Ansichtscontroller in einer Xamarin iOS 8-Anwendung anzuzeigen:

using MobileCoreServices;
...

// Allow the Document picker to select a range of document types
        var allowedUTIs = new string[] {
            UTType.UTF8PlainText,
            UTType.PlainText,
            UTType.RTF,
            UTType.PNG,
            UTType.Text,
            UTType.PDF,
            UTType.Image
        };

        // Display the picker
        //var picker = new UIDocumentPickerViewController (allowedUTIs, UIDocumentPickerMode.Open);
        var pickerMenu = new UIDocumentMenuViewController(allowedUTIs, UIDocumentPickerMode.Open);
        pickerMenu.DidPickDocumentPicker += (sender, args) => {

            // Wireup Document Picker
            args.DocumentPicker.DidPickDocument += (sndr, pArgs) => {

                // IMPORTANT! You must lock the security scope before you can
                // access this file
                var securityEnabled = pArgs.Url.StartAccessingSecurityScopedResource();

                // Open the document
                ThisApp.OpenDocument(pArgs.Url);

                // IMPORTANT! You must release the security lock established
                // above.
                pArgs.Url.StopAccessingSecurityScopedResource();
            };

            // Display the document picker
            PresentViewController(args.DocumentPicker,true,null);
        };

pickerMenu.ModalPresentationStyle = UIModalPresentationStyle.Popover;
PresentViewController(pickerMenu,true,null);
UIPopoverPresentationController presentationPopover = pickerMenu.PopoverPresentationController;
if (presentationPopover!=null) {
    presentationPopover.SourceView = this.View;
    presentationPopover.PermittedArrowDirections = UIPopoverArrowDirection.Down;
    presentationPopover.SourceRect = ((UIButton)s).Frame;
}

Wichtig

Der Entwickler muss die StartAccessingSecurityScopedResource Methode aufrufen NSUrl , bevor auf ein externes Dokument zugegriffen werden kann. Die StopAccessingSecurityScopedResource Methode muss aufgerufen werden, um die Sicherheitssperre freizugeben, sobald das Dokument geladen wurde.

Beispielausgabe

Nachfolgend sehen Sie ein Beispiel dafür, wie der obige Code eine Dokumentauswahl anzeigen würde, wenn sie auf einem i Telefon Gerät ausgeführt wird:

  1. Der Benutzer startet die Anwendung, und die Standard-Benutzeroberfläche wird angezeigt:

    Die Standard-Schnittstelle wird angezeigt.

  2. Der Benutzer tippt oben auf dem Bildschirm auf die Interaktive Schaltfläche und wird aufgefordert, einen Dokumentanbieter aus der Liste der verfügbaren Anbieter auszuwählen:

    Wählen Sie einen Dokumentanbieter aus der Liste der verfügbaren Anbieter aus.

  3. Der Dokumentauswahl-Ansichtscontroller wird für den ausgewählten Dokumentanbieter angezeigt:

    Der Ansichtscontroller für die Dokumentauswahl wird angezeigt.

  4. Der Benutzer tippt auf einen Dokumentordner , um dessen Inhalt anzuzeigen:

    Inhalt des Dokumentordners

  5. Der Benutzer wählt ein Dokument aus, und die Dokumentauswahl wird geschlossen.

  6. Die Standard Schnittstelle wird erneut angezeigt, das Dokument wird aus dem externen Container geladen und dessen Inhalt angezeigt.

Die tatsächliche Anzeige des Dokumentauswahl-Ansichtscontrollers hängt von den Dokumentanbietern ab, die der Benutzer auf dem Gerät installiert hat und welcher Dokumentauswahlmodus implementiert wurde. Im obigen Beispiel wird der Offene Modus verwendet, die anderen Modustypen werden im Folgenden ausführlich erläutert.

Verwalten externer Dokumente

Wie oben beschrieben, konnte eine Anwendung vor iOS 8 nur auf Dokumente zugreifen, die Teil des Anwendungscontainers waren. In iOS 8 kann eine Anwendung von externen Quellen auf Dokumente zugreifen:

Übersicht über das Verwalten externer Dokumente

Wenn der Benutzer ein Dokument aus einer externen Quelle auswählt, wird ein Referenzdokument in den Anwendungscontainer geschrieben, der auf das ursprüngliche Dokument verweist.

Um diese neue Möglichkeit zu vorhandenen Anwendungen hinzuzufügen, wurden der API mehrere neue Features hinzugefügt NSMetadataQuery . In der Regel verwendet eine Anwendung den Ubiquitous-Dokumentbereich zum Auflisten von Dokumenten, die sich im Anwendungscontainer befinden. Bei Verwendung dieses Bereichs werden weiterhin nur Dokumente im Anwendungscontainer angezeigt.

Wenn Sie den neuen Ubiquitous External Document Scope verwenden, werden Dokumente zurückgegeben, die sich außerhalb des Anwendungscontainers befinden und die Metadaten für sie zurückgeben. Der NSMetadataItemUrlKey Zeiger verweist auf die URL, in der sich das Dokument tatsächlich befindet.

Manchmal möchte eine Anwendung nicht mit den Dokumenten arbeiten, auf die durch die Referenz verwiesen wird. Stattdessen möchte die App direkt mit dem Referenzdokument arbeiten. Beispielsweise kann die App das Dokument im Ordner "Anwendung" auf der Benutzeroberfläche anzeigen oder dem Benutzer erlauben, die Verweise in einen Ordner zu verschieben.

In iOS 8 wurde ein neuer NSMetadataItemUrlInLocalContainerKey Zugriff auf das Referenzdokument direkt bereitgestellt. Dieser Schlüssel verweist auf den tatsächlichen Verweis auf das externe Dokument in einem Anwendungscontainer.

Es NSMetadataUbiquitousItemIsExternalDocumentKey wird verwendet, um zu testen, ob ein Dokument außerhalb des Containers einer Anwendung liegt. Dies NSMetadataUbiquitousItemContainerDisplayNameKey wird verwendet, um auf den Namen des Containers zuzugreifen, der die originale Kopie eines externen Dokuments enthält.

Warum Dokumentverweise erforderlich sind

Der Standard Grund, warum iOS 8 Verweise für den Zugriff auf externe Dokumente verwendet, ist Sicherheit. Keine Anwendung erhält Zugriff auf den Container einer anderen Anwendung. Nur die Dokumentauswahl kann dies tun, da der Prozess nicht mehr verarbeitet wird und über systemweiten Zugriff verfügt.

Die einzige Möglichkeit zum Aufrufen eines Dokuments außerhalb des Anwendungscontainers ist die Verwendung der Dokumentauswahl, und wenn die von der Auswahl zurückgegebene URL "Sicherheitsbereich" lautet. Die URL für den Sicherheitsbereich enthält nur genügend Informationen, um das Dokument zusammen mit den bereichsbezogenen Rechten auszuwählen, die zum Gewähren eines Anwendungszugriffs auf das Dokument erforderlich sind.

Es ist wichtig zu beachten, dass, wenn die URL mit Sicherheitsbereich in eine Zeichenfolge serialisiert und dann de serialisiert wurde, die Sicherheitsinformationen verloren gehen und die Datei von der URL aus nicht darauf zugreifen kann. Das Feature "Dokumentreferenz" bietet einen Mechanismus, mit dem sie von diesen URLs auf die Dateien zurückgegriffen werden können, auf die verwiesen wird.

Wenn die Anwendung also einen NSUrl von einem der Referenzdokumente erwirbt, verfügt sie bereits über den angefügten Sicherheitsbereich und kann für den Zugriff auf die Datei verwendet werden. Aus diesem Grund wird dringend empfohlen, dass der Entwickler diese UIDocument Informationen und Prozesse für sie verarbeitet.

Verwenden von Textmarken

Es ist nicht immer möglich, die Dokumente einer Anwendung auflisten, um zu einem bestimmten Dokument zurückzukehren, z. B. bei der Wiederherstellung des Zustands. iOS 8 bietet einen Mechanismus zum Erstellen von Lesezeichen, die direkt auf ein bestimmtes Dokument abzielen.

Der folgende Code erstellt eine Textmarke aus einer EigenschaftFileUrl:UIDocument

// Trap all errors
try {
    // Values to include in the bookmark packet
    var resources = new string[] {
        NSUrl.FileSecurityKey,
        NSUrl.ContentModificationDateKey,
        NSUrl.FileResourceIdentifierKey,
        NSUrl.FileResourceTypeKey,
        NSUrl.LocalizedNameKey
    };

    // Create the bookmark
    NSError err;
    Bookmark = Document.FileUrl.CreateBookmarkData (NSUrlBookmarkCreationOptions.WithSecurityScope, resources, iCloudUrl, out err);

    // Was there an error?
    if (err != null) {
        // Yes, report it
        Console.WriteLine ("Error Creating Bookmark: {0}", err.LocalizedDescription);
    }
}
catch (Exception e) {
    // Report error
    Console.WriteLine ("Error: {0}", e.Message);
}

Die vorhandene Lesezeichen-API wird verwendet, um ein Lesezeichen für eine vorhandene NSUrl zu erstellen, die gespeichert und geladen werden kann, um direkten Zugriff auf eine externe Datei zu ermöglichen. Der folgende Code stellt eine Textmarke wieder her, die oben erstellt wurde:

if (Bookmark != null) {
    // Trap all errors
    try {
        // Yes, attempt to restore it
        bool isBookmarkStale;
        NSError err;
        var srcUrl = new NSUrl (Bookmark, NSUrlBookmarkResolutionOptions.WithSecurityScope, iCloudUrl, out isBookmarkStale, out err);

        // Was there an error?
        if (err != null) {
            // Yes, report it
            Console.WriteLine ("Error Loading Bookmark: {0}", err.LocalizedDescription);
        } else {
            // Load document from bookmark
            OpenDocument (srcUrl);
        }
    }
    catch (Exception e) {
        // Report error
        Console.WriteLine ("Error: {0}", e.Message);
    }
}

Öffnen im Vergleich zum Importmodus und der Dokumentauswahl

Der Ansichtscontroller für die Dokumentauswahl bietet zwei verschiedene Betriebsmodi:

  1. Modus öffnen – In diesem Modus erstellt die Dokumentauswahl beim Auswählen und externen Dokument eine Textmarke mit Sicherheitsbereich im Anwendungscontainer.

    Eine sicherheitsbereichsbezogene Textmarke im Anwendungscontainer

  2. Importmodus : Wenn der Benutzer ein Dokument auswählt und externes Dokument auswählt, erstellt die Dokumentauswahl keine Textmarke, sondern kopiert die Datei stattdessen in einen temporären Speicherort und stellt der Anwendung zugriff auf das Dokument an diesem Speicherort bereit:

    Die Dokumentauswahl kopiert die Datei an einen temporären Speicherort und stellt der Anwendung Zugriff auf das Dokument an diesem Speicherort bereit.
    Sobald die Anwendung aus irgendeinem Grund beendet wurde, wird der temporäre Speicherort geleert und die Datei entfernt. Wenn die Anwendung den Zugriff auf die Datei Standard beibehalten muss, sollte sie eine Kopie erstellen und in ihrem Anwendungscontainer platzieren.

Der Modus "Öffnen" ist nützlich, wenn die Anwendung mit einer anderen Anwendung zusammenarbeiten möchte und alle Am Dokument vorgenommenen Änderungen mit dieser Anwendung freigeben möchte. Der Importmodus wird verwendet, wenn die Anwendung ihre Änderungen an einem Dokument nicht für andere Anwendungen freigeben möchte.

Externes Erstellen eines Dokuments

Wie bereits erwähnt, hat eine iOS 8-Anwendung keinen Zugriff auf Container außerhalb ihres eigenen Anwendungscontainers. Die Anwendung kann lokal oder in einen temporären Speicherort in einen eigenen Container schreiben und dann einen speziellen Dokumentmodus verwenden, um das resultierende Dokument außerhalb des Anwendungscontainers an einen vom Benutzer ausgewählten Speicherort zu verschieben.

Gehen Sie wie folgt vor, um ein Dokument an eine externe Position zu verschieben:

  1. Erstellen Sie zuerst ein neues Dokument an einem lokalen oder temporären Speicherort.
  2. Erstellen Sie ein NSUrl Element, das auf das neue Dokument verweist.
  3. Öffnen Sie einen neuen Dokumentauswahl-Ansichtscontroller, und übergeben Sie ihn mit NSUrl dem Modus von MoveToService .
  4. Nachdem der Benutzer einen neuen Speicherort ausgewählt hat, wird das Dokument von seiner aktuellen Position an die neue Position verschoben.
  5. Ein Referenzdokument wird in den Anwendungscontainer der App geschrieben, sodass auf die Datei weiterhin durch die erstellungsanwendung zugegriffen werden kann.

Der folgende Code kann verwendet werden, um ein Dokument an einen externen Speicherort zu verschieben: var picker = new UIDocumentPickerViewController (srcURL, UIDocumentPickerMode.MoveToService);

Das vom obigen Prozess zurückgegebene Referenzdokument ist identisch mit einem Dokument, das vom Öffnenmodus der Dokumentauswahl erstellt wurde. Es gibt jedoch Zeiten, in denen die Anwendung ein Dokument verschieben möchte, ohne einen Verweis darauf zu behalten.

Um ein Dokument zu verschieben, ohne einen Verweis zu generieren, verwenden Sie den ExportToService Modus. Beispiel: var picker = new UIDocumentPickerViewController (srcURL, UIDocumentPickerMode.ExportToService);

Wenn Sie den ExportToService Modus verwenden, wird das Dokument in den externen Container kopiert, und die vorhandene Kopie verbleibt an seinem ursprünglichen Speicherort.

Dokumentanbietererweiterungen

Mit iOS 8 möchte Apple, dass der Endbenutzer unabhängig davon, wo er tatsächlich vorhanden ist, auf alle cloudbasierten Dokumente zugreifen kann. Um dieses Ziel zu erreichen, bietet iOS 8 einen neuen Mechanismus für die Dokumentanbietererweiterung.

Was ist eine Dokumentanbietererweiterung?

Einfach gesagt, eine Dokumentanbietererweiterung ist eine Möglichkeit für einen Entwickler oder einen Drittanbieter, einen alternativen Dokumentspeicher für anwendungen bereitzustellen, auf die genau auf die gleiche Weise wie der vorhandene iCloud-Speicherort zugegriffen werden kann.

Der Benutzer kann einen dieser alternativen Speicherorte aus der Dokumentauswahl auswählen, und er kann die gleichen Zugriffsmodi (Öffnen, Importieren, Verschieben oder Exportieren) verwenden, um mit Dateien an diesem Speicherort zu arbeiten.

Dies wird mithilfe von zwei verschiedenen Erweiterungen implementiert:

  • Dokumentauswahlerweiterung – Stellt eine UIViewController Unterklasse bereit, die dem Benutzer eine grafische Benutzeroberfläche zum Auswählen eines Dokuments an einem alternativen Speicherort bietet. Diese Unterklasse wird als Teil des Dokumentauswahl-Ansichtscontrollers angezeigt.
  • Dateierweiterung – Dies ist eine Nicht-UI-Erweiterung, die sich mit der tatsächlichen Bereitstellung der Dateiinhalte befasst. Diese Erweiterungen werden über Die Dateikoordination ( NSFileCoordinator ) bereitgestellt. Dies ist ein weiterer wichtiger Fall, in dem die Dateikoordination erforderlich ist.

Das folgende Diagramm zeigt den typischen Datenfluss beim Arbeiten mit Dokumentanbietererweiterungen:

Dieses Diagramm zeigt den typischen Datenfluss beim Arbeiten mit Dokumentanbietererweiterungen

Der folgende Prozess läuft ab:

  1. Die Anwendung zeigt einen Dokumentauswahlcontroller an, damit der Benutzer eine Datei auswählen kann, mit der sie arbeiten kann.
  2. Der Benutzer wählt einen alternativen Dateispeicherort aus, und die benutzerdefinierte UIViewController Erweiterung wird aufgerufen, um die Benutzeroberfläche anzuzeigen.
  3. Der Benutzer wählt eine Datei aus diesem Speicherort aus, und die URL wird an die Dokumentauswahl zurückgegeben.
  4. Die Dokumentauswahl wählt die URL der Datei aus und gibt sie an die Anwendung zurück, an der der Benutzer arbeiten kann.
  5. Die URL wird an den Dateikoordinator übergeben, um den Inhalt der Dateien an die Anwendung zurückzugeben.
  6. Der Dateikoordinator ruft die benutzerdefinierte Dateianbietererweiterung auf, um die Datei abzurufen.
  7. Der Inhalt der Datei wird an den Dateikoordinator zurückgegeben.
  8. Der Inhalt der Datei wird an die Anwendung zurückgegeben.

Sicherheit und Lesezeichen

In diesem Abschnitt wird schnell erläutert, wie der Sicherheits- und persistente Dateizugriff über Lesezeichen mit Dokumentanbietererweiterungen funktioniert. Im Gegensatz zum iCloud-Dokumentanbieter, der Sicherheit und Lesezeichen automatisch im Anwendungscontainer speichert, sind Dokumentanbietererweiterungen nicht teil des Dokumentverweissystems.

Beispiel: In einer Unternehmenseinstellung, die einen eigenen unternehmensweiten sicheren Datenspeicher bereitstellt, möchten Administratoren keine vertraulichen Unternehmensinformationen, auf die von den öffentlichen iCloud-Servern zugegriffen oder verarbeitet wird. Daher kann das integrierte Dokumentreferenzsystem nicht verwendet werden.

Das Bookmark-System kann weiterhin verwendet werden, und es liegt in der Verantwortung der Dateianbietererweiterung, eine mit Textmarken versehene URL ordnungsgemäß zu verarbeiten und den Inhalt des Dokuments zurückzugeben, auf das darauf verwiesen wird.

Für Sicherheitszwecke verfügt iOS 8 über eine Isolationsebene, die die Informationen über welche Anwendung zugriff auf welchen Bezeichner innerhalb des Dateianbieters enthält. Beachten Sie, dass der gesamte Dateizugriff von dieser Isolationsschicht gesteuert wird.

Das folgende Diagramm zeigt den Datenfluss beim Arbeiten mit Textmarken und einer Dokumentanbietererweiterung:

Dieses Diagramm zeigt den Datenfluss beim Arbeiten mit Textmarken und einer Dokumentanbietererweiterung.

Der folgende Prozess läuft ab:

  1. Die Anwendung ist dabei, den Hintergrund einzugeben und den Status beizubehalten. Es wird aufgerufen NSUrl , eine Textmarke für eine Datei im alternativen Speicher zu erstellen.
  2. NSUrl ruft die Dateianbietererweiterung auf, um eine persistente URL zum Dokument abzurufen.
  3. Die Dateianbietererweiterung gibt die URL als Zeichenfolge an die NSUrl .
  4. Die NSUrl URL wird in eine Textmarke bündelt und an die Anwendung zurückgegeben.
  5. Wenn die Anwendung nicht im Hintergrund ist und den Zustand wiederherstellen muss, übergibt sie die Textmarke an NSUrl .
  6. NSUrl ruft die Dateianbietererweiterung mit der URL der Datei auf.
  7. Der Dateierweiterungsanbieter greift auf die Datei zu und gibt den Speicherort der Datei an NSUrl .
  8. Der Dateispeicherort wird mit Sicherheitsinformationen gebündelt und an die Anwendung zurückgegeben.

Von hier aus kann die Anwendung auf die Datei zugreifen und wie gewohnt damit arbeiten.

Schreiben von Dateien

In diesem Abschnitt wird schnell erläutert, wie das Schreiben von Dateien an einen alternativen Speicherort mit einer Dokumentanbietererweiterung funktioniert. Die iOS-Anwendung verwendet die Dateikoordination, um Informationen auf dem Datenträger im Anwendungscontainer zu speichern. Kurz nachdem die Datei erfolgreich geschrieben wurde, wird die Dateianbietererweiterung über die Änderung benachrichtigt.

An diesem Punkt kann die Dateianbietererweiterung mit dem Hochladen der Datei an den alternativen Speicherort beginnen (oder die Datei als modifiziert markieren und einen Upload erfordern).

Erstellen neuer Dokumentanbietererweiterungen

Das Erstellen neuer Dokumentanbietererweiterungen liegt außerhalb des Gültigkeitsbereichs dieses Einführungsartikels. Diese Informationen werden hier bereitgestellt, um zu zeigen, dass eine Anwendung basierend auf den Erweiterungen, die ein Benutzer in sein iOS-Gerät geladen hat, Zugriff auf Dokumentspeicherorte außerhalb des von Apple bereitgestellten iCloud-Speicherorts hat.

Dieser Umstand sollte vom Entwickler bei Verwendung der Dokumentauswahl und beim Arbeiten mit externen Dokumenten beachtet werden. Sie sollten nicht davon ausgehen, dass dieses Dokument in iCloud gehostet wird.

Weitere Informationen zum Erstellen eines Speicheranbieters oder einer Dokumentauswahlerweiterung finden Sie im Dokument "Einführung in App-Erweiterungen ".

Migrieren zu iCloud Drive

Unter iOS 8 können Benutzer das vorhandene iCloud Documents System weiterhin verwenden, das in iOS 7 (und früheren Systemen) verwendet wird, oder sie können auswählen, vorhandene Dokumente zum neuen iCloud Drive-Mechanismus zu migrieren.

Auf Mac OS X Yosemite bietet Apple nicht die Abwärtskompatibilität, sodass alle Dokumente auf iCloud Drive migriert werden müssen oder sie nicht mehr geräteübergreifend aktualisiert werden.

Nachdem das Konto eines Benutzers zu iCloud Drive migriert wurde, können nur Geräte, die iCloud Drive verwenden, Änderungen an Dokumente auf diesen Geräten weitergeben.

Wichtig

Entwickler sollten beachten, dass die in diesem Artikel behandelten neuen Features nur verfügbar sind, wenn das Konto des Benutzers zu iCloud Drive migriert wurde.

Zusammenfassung

In diesem Artikel wurden die Änderungen an vorhandenen iCloud-APIs behandelt, die erforderlich sind, um iCloud Drive und den neuen Dokumentauswahl-Ansichtscontroller zu unterstützen. Sie hat die Dateikoordination behandelt und warum es wichtig ist, wenn Sie mit cloudbasierten Dokumenten arbeiten. Es wurde das Setup behandelt, das erforderlich ist, um cloudbasierte Dokumente in einer Xamarin.iOS-Anwendung zu aktivieren und einen einführenden Blick auf die Arbeit mit Dokumenten außerhalb des Anwendungscontainers einer App mithilfe des Dokumentauswahl-Ansichtscontrollers zu erhalten.

Darüber hinaus behandelte dieser Artikel kurz Dokumentanbietererweiterungen und warum der Entwickler sie beim Schreiben von Anwendungen kennen sollte, die cloudbasierte Dokumente verarbeiten können.