Udostępnij za pośrednictwem


Selektor dokumentów na platformie Xamarin.iOS

Selektor dokumentów umożliwia udostępnianie dokumentów między aplikacjami. Te dokumenty mogą być przechowywane w usłudze iCloud lub w katalogu innej aplikacji. Dokumenty są udostępniane za pośrednictwem zestawu rozszerzeń dostawcy dokumentów, które użytkownik zainstalował na swoim urządzeniu.

Ze względu na trudności z synchronizowaniem dokumentów między aplikacjami i chmurą wprowadzają pewną ilość niezbędnej złożoności.

Wymagania

Do wykonania kroków przedstawionych w tym artykule są wymagane następujące czynności:

  • Xcode 7 i iOS 8 lub nowsze — na komputerze dewelopera muszą być zainstalowane i nowsze interfejsy API Xcode 7 i iOS 8 lub nowsze.
  • Visual Studio lub Visual Studio dla komputerów Mac — należy zainstalować najnowszą wersję Visual Studio dla komputerów Mac.
  • Urządzenie z systemem iOS — urządzenie z systemem iOS 8 lub nowszym.

Zmiany w usłudze iCloud

Aby zaimplementować nowe funkcje selektora dokumentów, wprowadzono następujące zmiany w usłudze iCloud firmy Apple:

  • Demon iCloud został całkowicie przepisany przy użyciu biblioteki CloudKit.
  • Nazwa istniejących funkcji usługi iCloud została zmieniona na iCloud Drive.
  • Dodano obsługę systemu operacyjnego Microsoft Windows do usługi iCloud.
  • Folder iCloud został dodany w narzędziu Mac OS Finder.
  • Urządzenia z systemem iOS mogą uzyskiwać dostęp do zawartości folderu mac OS iCloud.

Ważne

Firma Apple udostępnia narzędzia pomagające deweloperom w prawidłowym obsłudze ogólnego rozporządzenia o ochronie danych (RODO) Unii Europejskiej.

Co to jest dokument?

W przypadku odwoływania się do dokumentu w usłudze iCloud jest to pojedyncza, autonomiczna jednostka i powinna być postrzegana jako taka przez użytkownika. Użytkownik może chcieć zmodyfikować dokument lub udostępnić go innym użytkownikom (na przykład przy użyciu poczty e-mail).

Istnieje kilka typów plików, które użytkownik natychmiast rozpozna jako dokumenty, takie jak strony, prezentacja lub pliki Numbers. Jednak usługa iCloud nie jest ograniczona do tej koncepcji. Na przykład stan gry (na przykład mecz szachowy) może być traktowany jako dokument i przechowywany w usłudze iCloud. Ten plik można przekazać między urządzeniami użytkownika i umożliwić im odbiór gry, w której została przerwana na innym urządzeniu.

Obsługa dokumentów

Przed rozpoczęciem pracy z kodem wymaganym do korzystania z selektora dokumentów za pomocą platformy Xamarin ten artykuł zawiera najlepsze rozwiązania dotyczące pracy z dokumentami usługi iCloud oraz kilka modyfikacji wprowadzonych w istniejących interfejsach API wymaganych do obsługi selektora dokumentów.

Korzystanie z koordynacji plików

Ponieważ plik można zmodyfikować z kilku różnych lokalizacji, należy użyć koordynacji, aby zapobiec utracie danych.

Korzystanie z koordynacji plików

Przyjrzyjmy się powyższej ilustracji:

  1. Urządzenie z systemem iOS korzystające z koordynacji plików tworzy nowy dokument i zapisuje go w folderze iCloud.
  2. Usługa iCloud zapisuje zmodyfikowany plik w chmurze na potrzeby dystrybucji na każdym urządzeniu.
  3. Dołączony komputer Mac widzi zmodyfikowany plik w folderze iCloud i używa koordynacji plików w celu skopiowania zmian do pliku.
  4. Urządzenie, które nie korzysta z koordynacji plików, powoduje zmianę pliku i zapisuje je w folderze iCloud. Te zmiany są natychmiast replikowane do innych urządzeń.

Załóżmy, że oryginalne urządzenie z systemem iOS lub komputer Mac edytował plik, a teraz zmiany zostaną utracone i zastąpione wersją pliku z urządzenia niezporządkowanego. Aby zapobiec utracie danych, koordynacja plików jest wymagana podczas pracy z dokumentami opartymi na chmurze.

Korzystanie z narzędzia UIDocument

UIDocument sprawia, że wszystko jest proste (lub NSDocument w systemie macOS), wykonując wszystkie ciężkie zadania dla dewelopera. Zapewnia wbudowaną koordynację plików z kolejkami w tle, aby uniemożliwić blokowanie interfejsu użytkownika aplikacji.

UIDocument Uwidacznia wiele interfejsów API wysokiego poziomu, które ułatwiają tworzenie aplikacji platformy Xamarin w dowolnym celu wymaganym przez dewelopera.

Poniższy kod tworzy podklasę UIDocument w celu zaimplementowania ogólnego dokumentu tekstowego, który może służyć do przechowywania i pobierania tekstu z usługi iCloud:

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

Klasa przedstawiona GenericTextDocument powyżej będzie używana w tym artykule podczas pracy z selektorem dokumentów i dokumentami zewnętrznymi w aplikacji Xamarin.iOS 8.

Asynchroniczna koordynacja plików

System iOS 8 udostępnia kilka nowych funkcji asynchronicznej koordynacji plików za pośrednictwem nowych interfejsów API koordynacji plików. Przed systemem iOS 8 wszystkie istniejące interfejsy API koordynacji plików były całkowicie synchroniczne. Oznaczało to, że deweloper był odpowiedzialny za zaimplementowanie własnej kolejki w tle, aby uniemożliwić koordynację plików blokowanie interfejsu użytkownika aplikacji.

Nowa NSFileAccessIntent klasa zawiera adres URL wskazujący plik i kilka opcji kontrolowania wymaganego typu koordynacji. Poniższy kod demonstruje przeniesienie pliku z jednej lokalizacji do innej przy użyciu intencji:

// 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);
    }
});

Odnajdywanie i wyświetlanie listy dokumentów

Sposobem odnajdywania i wyświetlania listy dokumentów jest użycie istniejących NSMetadataQuery interfejsów API. W tej sekcji omówiono nowe funkcje dodane do NSMetadataQuery tej funkcji, dzięki czemu praca z dokumentami będzie jeszcze łatwiejsza niż wcześniej.

Istniejące zachowanie

Przed systemem iOS 8 powolne było odbieranie lokalnych zmian plików, NSMetadataQuery takich jak: usuwanie, tworzenie i zmienianie nazw.

Omówienie zmian pliku lokalnego NSMetadataQuery

Na powyższym diagramie:

  1. W przypadku plików, które już istnieją w kontenerze aplikacji, istniejące NSMetadata rekordy zostały wstępnie utworzone i buforowane, NSMetadataQuery aby były natychmiast dostępne dla aplikacji.
  2. Aplikacja tworzy nowy plik w kontenerze aplikacji.
  3. Istnieje opóźnienie przed NSMetadataQuery sprawdzeniem modyfikacji kontenera aplikacji i utworzeniem wymaganego NSMetadata rekordu.

Ze względu na opóźnienie tworzenia rekordu NSMetadata aplikacja musiała mieć otwarte dwa źródła danych: jedno dla zmian plików lokalnych i jedno dla zmian opartych na chmurze.

Szycia

W systemie iOS 8 NSMetadataQuery łatwiej jest używać bezpośrednio z nową funkcją o nazwie Stitching:

NSMetadataQuery z nową funkcją o nazwie Stitching

Za pomocą łączenia na powyższym diagramie:

  1. Tak jak wcześniej, w przypadku plików, które już istnieją w kontenerze aplikacji, NSMetadataQuery istniejące NSMetadata rekordy zostały wstępnie utworzone i buforowane.
  2. Aplikacja tworzy nowy plik w kontenerze aplikacji przy użyciu koordynacji plików.
  3. Punkt zaczepienia w kontenerze aplikacji widzi modyfikację i wywołuje metodę NSMetadataQuery tworzenia wymaganego NSMetadata rekordu.
  4. Rekord NSMetadata jest tworzony bezpośrednio po pliku i jest udostępniany aplikacji.

Przy użyciu łączenia aplikacji nie trzeba już otwierać źródła danych w celu monitorowania zmian plików lokalnych i w chmurze. Teraz aplikacja może polegać bezpośrednio na NSMetadataQuery .

Ważne

Łączenie działa tylko wtedy, gdy aplikacja korzysta z koordynacji plików, jak pokazano w powyższej sekcji. Jeśli koordynacja plików nie jest używana, interfejsy API są domyślne dla istniejącego zachowania systemu iOS 8.

Nowe funkcje metadanych systemu iOS 8

W systemie iOS 8 dodano NSMetadataQuery następujące nowe funkcje:

  • NSMetatadataQuery Program może teraz wyświetlać listę dokumentów innych niż lokalne przechowywane w chmurze.
  • Dodano nowe interfejsy API w celu uzyskania dostępu do informacji o metadanych w dokumentach opartych na chmurze.
  • Istnieje nowy NSUrl_PromisedItems interfejs API, który będzie uzyskiwać dostęp do atrybutów pliku plików, które mogą lub nie mają dostępnej zawartości lokalnie.
  • GetPromisedItemResourceValue Użyj metody , aby uzyskać informacje o danym pliku lub użyć GetPromisedItemResourceValues metody , aby uzyskać informacje na temat więcej niż jednego pliku jednocześnie.

Dodano dwie nowe flagi koordynacji plików do obsługi metadanych:

  • NSFileCoordinatorReadImmediatelyAvailableMetadataOnly
  • NSFileCoordinatorWriteContentIndependentMetadataOnly

Po powyższych flagach zawartość pliku dokumentu nie musi być dostępna lokalnie, aby mogły być używane.

Poniższy segment kodu pokazuje, jak używać NSMetadataQuery do wykonywania zapytań o istnienie określonego pliku i skompilować plik, jeśli nie istnieje:

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

Miniatury dokumentu

Firma Apple uważa, że najlepszym środowiskiem użytkownika podczas wyświetlania listy dokumentów dla aplikacji jest korzystanie z wersji zapoznawczych. Dzięki temu użytkownicy końcowi mogą szybko identyfikować dokument, z którymi chcą pracować.

Przed systemem iOS 8 wyświetlanie podglądów dokumentów wymaga implementacji niestandardowej. Nowość w systemie iOS 8 to atrybuty systemu plików, które umożliwiają deweloperowi szybką pracę z miniaturami dokumentów.

Pobieranie miniatur dokumentów

Wywołując GetPromisedItemResourceValue metody lub GetPromisedItemResourceValues , NSUrl_PromisedItems interfejs API, NSUrlThumbnailDictionary, jest zwracany. Jedynym kluczem aktualnie w tym słowniku NSThumbnial1024X1024SizeKey jest element i jego dopasowanie UIImage.

Zapisywanie miniatur dokumentów

Najprostszym sposobem zapisania miniatury jest użycie polecenia UIDocument. Wywołując metodę GetFileAttributesToWriteUIDocument i ustawiając miniaturę, zostanie ona automatycznie zapisana po utworzeniu pliku dokumentu. Demon usługi iCloud zobaczy tę zmianę i rozpropaguje ją do usługi iCloud. W systemie Mac OS X miniatury są generowane automatycznie dla dewelopera przez wtyczkę Quick Look.

Mając podstawowe informacje na temat pracy z dokumentami opartymi na usłudze iCloud, wraz z modyfikacjami istniejącego interfejsu API, możemy zaimplementować kontroler widoku selektora dokumentów w aplikacji mobilnej platformy Xamarin iOS 8.

Włączanie usługi iCloud na platformie Xamarin

Przed użyciem selektora dokumentów w aplikacji platformy Xamarin.iOS należy włączyć obsługę usługi iCloud zarówno w aplikacji, jak i za pośrednictwem firmy Apple.

W poniższych krokach przedstawiono proces aprowizacji w usłudze iCloud.

  1. Utwórz kontener usługi iCloud.
  2. Utwórz identyfikator aplikacji zawierający usługę App Service w usłudze iCloud.
  3. Utwórz profil aprowizacji zawierający ten identyfikator aplikacji.

Przewodnik Praca z możliwościami zawiera instrukcje opisane w dwóch pierwszych krokach. Aby utworzyć profil aprowizacji, wykonaj kroki opisane w przewodniku Profil aprowizacji.

W poniższych krokach przedstawiono proces konfigurowania aplikacji dla usługi iCloud:

Należy wykonać następujące czynności:

  1. Otwórz projekt w programie Visual Studio dla komputerów Mac lub Visual Studio.

  2. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz pozycję Opcje.

  3. W oknie dialogowym Opcje wybierz pozycję Aplikacja systemu iOS, upewnij się, że identyfikator pakietu jest zgodny z identyfikatorem pakietu zdefiniowanym w identyfikatorze aplikacji utworzonym powyżej dla aplikacji.

  4. Wybierz pozycję Podpisywanie pakietu systemu iOS, wybierz tożsamość dewelopera i utworzony powyżej profil aprowizacji.

  5. Kliknij przycisk OK, aby zapisać zmiany i zamknąć okno dialogowe.

  6. Kliknij prawym przyciskiem myszy Entitlements.plist w Eksplorator rozwiązań, aby otworzyć go w edytorze.

    Ważne

    W programie Visual Studio może być konieczne otwarcie edytora uprawnień, klikając go prawym przyciskiem myszy, wybierając polecenie Otwórz za pomocą... i wybierając pozycję Edytor listy właściwości

  7. Zaznacz pozycję Włącz usługę iCloud , dokumenty iCloud, magazyn klucz-wartość i zestaw CloudKit.

  8. Upewnij się, że kontener istnieje dla aplikacji (jak utworzono powyżej). Przykład: iCloud.com.your-company.AppName

  9. Zapisz zmiany w pliku.

Aby uzyskać więcej informacji na temat uprawnień, zapoznaj się z przewodnikiem Praca z upoważnieniami .

Po zakończeniu powyższej konfiguracji aplikacja może teraz używać dokumentów w chmurze i nowego kontrolera widoku selektora dokumentów.

Wspólny kod konfiguracji

Przed rozpoczęciem pracy z kontrolerem widoku selektora dokumentów wymagany jest standardowy kod konfiguracji. Zacznij od zmodyfikowania pliku aplikacji AppDelegate.cs i utwórz go w następujący sposób:

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

Ważne

Powyższy kod zawiera kod z powyższej sekcji Odnajdywanie i wyświetlanie dokumentów. Jest on przedstawiony tutaj w całości, jak to się wydaje w rzeczywistej aplikacji. Dla uproszczenia ten przykład działa tylko z pojedynczym, zakodowanym plikiem (test.txt).

Powyższy kod uwidacznia kilka skrótów do dysku iCloud, aby ułatwić pracę w pozostałej części aplikacji.

Następnie dodaj następujący kod do dowolnego kontenera widoku lub widoku, który będzie korzystał z selektora dokumentów lub pracy z dokumentami opartymi na chmurze:

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

Spowoduje to dodanie skrótu w celu uzyskania dostępu do skrótów utworzonych powyżej i uzyskiwania dostępu do AppDelegate skrótów w usłudze iCloud.

W tym kodzie przyjrzyjmy się implementacji kontrolera widoku selektora dokumentów w aplikacji Xamarin iOS 8.

Korzystanie z kontrolera widoku selektora dokumentów

Przed systemem iOS 8 bardzo trudno było uzyskać dostęp do dokumentów z innej aplikacji, ponieważ nie było możliwości odnajdywania dokumentów spoza aplikacji z poziomu aplikacji.

Istniejące zachowanie

Omówienie istniejącego zachowania

Przyjrzyjmy się uzyskiwaniu dostępu do dokumentu zewnętrznego przed systemem iOS 8:

  1. Najpierw użytkownik musiałby otworzyć aplikację, która pierwotnie utworzyła dokument.
  2. Wybrano pozycję Dokument, a UIDocumentInteractionController element jest używany do wysyłania dokumentu do nowej aplikacji.
  3. Na koniec kopia oryginalnego dokumentu zostanie umieszczona w kontenerze nowej aplikacji.

W tym miejscu dokument jest dostępny dla drugiej aplikacji do otwierania i edytowania.

Odnajdywanie dokumentów poza kontenerem aplikacji

W systemie iOS 8 aplikacja może łatwo uzyskiwać dostęp do dokumentów spoza własnego kontenera aplikacji:

Odnajdywanie dokumentów poza kontenerem aplikacji

Przy użyciu nowego selektora dokumentów w usłudze iCloud ( UIDocumentPickerViewController) aplikacja systemu iOS może bezpośrednio odnajdywać kontener aplikacji i uzyskiwać do nie tylko do tego kontenera aplikacji. Zapewnia UIDocumentPickerViewController mechanizm udzielania użytkownikowi dostępu i edytowania odnalezionych dokumentów za pośrednictwem uprawnień.

Aplikacja musi wyrazić zgodę na wyświetlanie dokumentów w selektorze dokumentów w usłudze iCloud i być dostępne dla innych aplikacji do odnajdywania i pracy z nimi. Aby aplikacja Xamarin iOS 8 współużytkować swój kontener aplikacji, edytuj go Info.plist w standardowym edytorze tekstów i dodaj następujące dwa wiersze w dolnej części słownika (między tagami <dict>...</dict> ):

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

Zapewnia UIDocumentPickerViewController świetny nowy interfejs użytkownika, który umożliwia użytkownikowi wybór dokumentów. Aby wyświetlić kontroler widoku selektora dokumentów w aplikacji Xamarin iOS 8, wykonaj następujące czynności:

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

Ważne

Deweloper musi wywołać metodę StartAccessingSecurityScopedResourceNSUrl przed uzyskaniem dostępu do dokumentu zewnętrznego. Metoda StopAccessingSecurityScopedResource musi zostać wywołana, aby zwolnić blokadę zabezpieczeń zaraz po załadowaniu dokumentu.

Przykładowe dane wyjściowe

Oto przykład sposobu wyświetlania powyższego kodu selektora dokumentów podczas uruchamiania na urządzeniu i Telefon:

  1. Użytkownik uruchamia aplikację, a główny interfejs jest wyświetlany:

    Zostanie wyświetlony główny interfejs

  2. Użytkownik naciągnie przycisk akcji w górnej części ekranu i zostanie poproszony o wybranie dostawcy dokumentów z listy dostępnych dostawców:

    Wybierz dostawcę dokumentów z listy dostępnych dostawców

  3. Kontroler widoku selektora dokumentów jest wyświetlany dla wybranego dostawcy dokumentów:

    Zostanie wyświetlony kontroler widoku selektora dokumentów

  4. Użytkownik naciągnie folder dokumentu, aby wyświetlić jego zawartość:

    Zawartość folderu dokumentu

  5. Użytkownik wybierze dokument , a selektor dokumentów zostanie zamknięty.

  6. Główny interfejs jest odtwarzany ponownie, dokument jest ładowany z zewnętrznego kontenera i jego zawartości wyświetlanej.

Rzeczywiste wyświetlanie kontrolera widoku selektora dokumentów zależy od dostawców dokumentów, których użytkownik zainstalował na urządzeniu i który tryb selektora dokumentów został zaimplementowany. W powyższym przykładzie jest używany tryb otwierania, inne typy trybu zostaną szczegółowo omówione poniżej.

Zarządzanie dokumentami zewnętrznymi

Jak wspomniano powyżej, przed systemem iOS 8 aplikacja może uzyskiwać dostęp tylko do dokumentów, które były częścią kontenera aplikacji. W systemie iOS 8 aplikacja może uzyskiwać dostęp do dokumentów ze źródeł zewnętrznych:

Omówienie zarządzania dokumentami zewnętrznymi

Gdy użytkownik wybierze dokument ze źródła zewnętrznego, dokument referencyjny jest zapisywany w kontenerze aplikacji wskazującym oryginalny dokument.

Aby ułatwić dodawanie tej nowej możliwości do istniejących aplikacji, do interfejsu NSMetadataQuery API dodano kilka nowych funkcji. Zazwyczaj aplikacja używa wszechobecnego zakresu dokumentów do wyświetlania dokumentów znajdujących się w kontenerze aplikacji. Korzystając z tego zakresu, będą nadal wyświetlane tylko dokumenty w kontenerze aplikacji.

Użycie nowego wszechobecnego zakresu dokumentów zewnętrznych spowoduje zwrócenie dokumentów spoza kontenera aplikacji i zwrócenie metadanych dla nich. Spowoduje NSMetadataItemUrlKey to wskazanie adresu URL, pod którym rzeczywiście znajduje się dokument.

Czasami aplikacja nie chce pracować z dokumentami wskazywanymi przez odwołanie. Zamiast tego aplikacja chce pracować bezpośrednio z dokumentem referencyjnym. Na przykład aplikacja może chcieć wyświetlić dokument w folderze Aplikacja w interfejsie użytkownika lub zezwolić użytkownikowi na przenoszenie odwołań wewnątrz folderu.

W systemie iOS 8 udostępniono nowy NSMetadataItemUrlInLocalContainerKey dostęp bezpośrednio do dokumentu referencyjnego. Ten klucz wskazuje rzeczywiste odwołanie do dokumentu zewnętrznego w kontenerze aplikacji.

Służy NSMetadataUbiquitousItemIsExternalDocumentKey do testowania, czy dokument jest zewnętrzny dla kontenera aplikacji. Element NSMetadataUbiquitousItemContainerDisplayNameKey służy do uzyskiwania dostępu do nazwy kontenera, który zawiera oryginalną kopię dokumentu zewnętrznego.

Dlaczego odwołania do dokumentów są wymagane

Głównym powodem, dla którego system iOS 8 używa odwołań do uzyskiwania dostępu do dokumentów zewnętrznych, jest bezpieczeństwo. Żadna aplikacja nie ma dostępu do kontenera innej aplikacji. Tylko selektor dokumentów może to zrobić, ponieważ kończy się proces i ma dostęp do całego systemu.

Jedynym sposobem uzyskania dostępu do dokumentu spoza kontenera aplikacji jest użycie selektora dokumentów, a adres URL zwrócony przez selektor to Zakres zabezpieczeń. Adres URL o zakresie zabezpieczeń zawiera wystarczające informacje, aby wybrać dokument wraz z prawami o określonym zakresie wymaganymi do udzielenia aplikacji dostępu do dokumentu.

Należy pamiętać, że jeśli adres URL o zakresie zabezpieczeń został zserializowany w ciągu, a następnie zdyserializowany, informacje o zabezpieczeniach zostaną utracone, a plik będzie niedostępny z adresu URL. Funkcja odwołania do dokumentu udostępnia mechanizm powrotu do plików wskazywanych przez te adresy URL.

Jeśli więc aplikacja uzyskuje element NSUrl z jednego z dokumentów referencyjnych, ma już dołączony zakres zabezpieczeń i może służyć do uzyskiwania dostępu do pliku. Z tego powodu zdecydowanie zaleca się, aby deweloper używał UIDocument , ponieważ obsługuje wszystkie te informacje i procesy dla nich.

Korzystanie z zakładek

Nie zawsze można wyliczyć dokumenty aplikacji, aby wrócić do określonego dokumentu, na przykład podczas przywracania stanu. System iOS 8 udostępnia mechanizm tworzenia zakładek bezpośrednio przeznaczonych dla danego dokumentu.

Poniższy kod utworzy zakładkę na podstawie UIDocumentwłaściwości :FileUrl

// 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);
}

Istniejący interfejs API zakładek służy do tworzenia zakładki dla istniejącej NSUrl , którą można zapisać i załadować w celu zapewnienia bezpośredniego dostępu do pliku zewnętrznego. Poniższy kod przywróci zakładkę utworzoną powyżej:

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

Otwórz tryb importu i selektor dokumentów

Kontroler widoku selektora dokumentów zawiera dwa różne tryby operacji:

  1. Tryb otwierania — w tym trybie po wybraniu przez użytkownika i zewnętrznym dokumencie selektor dokumentów utworzy zakładkę z zakresem zabezpieczeń w kontenerze aplikacji.

    Zakładka o zakresie zabezpieczeń w kontenerze aplikacji

  2. Tryb importu — w tym trybie, gdy użytkownik wybierze i dokument zewnętrzny, selektor dokumentów nie utworzy zakładki, ale zamiast tego skopiuj plik do lokalizacji tymczasowej i zapewni aplikacji dostęp do dokumentu w tej lokalizacji:

    Selektor dokumentów skopiuje plik do lokalizacji tymczasowej i zapewni aplikacji dostęp do dokumentu w tej lokalizacji
    Po zakończeniu działania aplikacji z jakiegokolwiek powodu lokalizacja tymczasowa zostanie opróżniona i plik zostanie usunięty. Jeśli aplikacja musi zachować dostęp do pliku, powinna utworzyć kopię i umieścić ją w kontenerze aplikacji.

Tryb otwierania jest przydatny, gdy aplikacja chce współpracować z inną aplikacją i udostępniać wszelkie zmiany wprowadzone w dokumencie tej aplikacji. Tryb importu jest używany, gdy aplikacja nie chce udostępniać jej modyfikacji w dokumencie innym aplikacjom.

Tworzenie dokumentu zewnętrznego

Jak wspomniano powyżej, aplikacja systemu iOS 8 nie ma dostępu do kontenerów poza własnym kontenerem aplikacji. Aplikacja może zapisywać dane we własnym kontenerze lokalnie lub w lokalizacji tymczasowej, a następnie przenosić wynikowy dokument poza kontenerem aplikacji do wybranej przez użytkownika lokalizacji.

Aby przenieść dokument do lokalizacji zewnętrznej, wykonaj następujące czynności:

  1. Najpierw utwórz nowy dokument w lokalizacji lokalnej lub tymczasowej.
  2. Utwórz element NSUrl wskazujący nowy dokument.
  3. Otwórz nowy kontroler widoku selektora dokumentów i przekaż go NSUrl za pomocą trybu MoveToService .
  4. Gdy użytkownik wybierze nową lokalizację, dokument zostanie przeniesiony z bieżącej lokalizacji do nowej lokalizacji.
  5. Dokument referencyjny zostanie zapisany w kontenerze aplikacji aplikacji, dzięki czemu plik będzie nadal dostępny przez tworzenie aplikacji.

Poniższy kod może służyć do przenoszenia dokumentu do lokalizacji zewnętrznej: var picker = new UIDocumentPickerViewController (srcURL, UIDocumentPickerMode.MoveToService);

Dokument referencyjny zwrócony przez powyższy proces jest dokładnie taki sam jak dokument utworzony przez tryb otwierania selektora dokumentów. Jednak czasami aplikacja może chcieć przenieść dokument bez konieczności odwołowania się do niego.

Aby przenieść dokument bez generowania odwołania, użyj trybu ExportToService . Przykład: var picker = new UIDocumentPickerViewController (srcURL, UIDocumentPickerMode.ExportToService);

W przypadku korzystania z ExportToService trybu dokument jest kopiowany do zewnętrznego kontenera, a istniejąca kopia jest pozostawiona w oryginalnej lokalizacji.

Rozszerzenia dostawcy dokumentów

W systemie iOS 8 firma Apple chce, aby użytkownik końcowy mógł uzyskać dostęp do dowolnego z dokumentów opartych na chmurze, niezależnie od tego, gdzie rzeczywiście istnieją. Aby osiągnąć ten cel, system iOS 8 udostępnia nowy mechanizm rozszerzenia dostawcy dokumentów.

Co to jest rozszerzenie dostawcy dokumentów?

Po prostu określono, rozszerzenie dostawcy dokumentów jest sposobem dla dewelopera lub innej firmy, aby udostępnić alternatywnemu magazynowi dokumentów aplikacji, do którego można uzyskać dostęp w dokładnie taki sam sposób jak istniejąca lokalizacja magazynu iCloud.

Użytkownik może wybrać jedną z tych alternatywnych lokalizacji przechowywania z selektora dokumentów i używać dokładnie tych samych trybów dostępu (Otwórz, Importuj, Przenieś lub Eksportuj), aby pracować z plikami w tej lokalizacji.

Jest to implementowane przy użyciu dwóch różnych rozszerzeń:

  • Rozszerzenie selektora dokumentów — udostępnia podklasę UIViewController , która udostępnia interfejs graficzny użytkownika do wyboru dokumentu z alternatywnej lokalizacji przechowywania. Ta podklasa będzie wyświetlana jako część kontrolera widoku selektora dokumentów.
  • Rozszerzenie Udostępniania pliku — jest to rozszerzenie inne niż interfejs użytkownika, które zajmuje się dostarczaniem zawartości plików. Te rozszerzenia są udostępniane za pośrednictwem koordynacji plików ( NSFileCoordinator ). Jest to kolejny ważny przypadek, w którym wymagana jest koordynacja plików.

Na poniższym diagramie przedstawiono typowy przepływ danych podczas pracy z rozszerzeniami dostawcy dokumentów:

Ten diagram przedstawia typowy przepływ danych podczas pracy z rozszerzeniami dostawcy dokumentów

Następuje następujący proces:

  1. Aplikacja przedstawia kontroler selektora dokumentów, aby umożliwić użytkownikowi wybranie pliku do pracy.
  2. Użytkownik wybiera alternatywną lokalizację pliku, a rozszerzenie niestandardowe UIViewController jest wywoływane w celu wyświetlenia interfejsu użytkownika.
  3. Użytkownik wybiera plik z tej lokalizacji, a adres URL jest przekazywany z powrotem do selektora dokumentów.
  4. Selektor dokumentów wybiera adres URL pliku i zwraca go do aplikacji, aby użytkownik pracował.
  5. Adres URL jest przekazywany do koordynatora plików w celu zwrócenia zawartości plików do aplikacji.
  6. Koordynator plików wywołuje niestandardowe rozszerzenie dostawcy plików, aby pobrać plik.
  7. Zawartość pliku jest zwracana do koordynatora plików.
  8. Zawartość pliku jest zwracana do aplikacji.

Zabezpieczenia i zakładki

W tej sekcji przedstawiono, jak zabezpieczenia i trwały dostęp do plików za pośrednictwem zakładek współdziałają z rozszerzeniami dostawcy dokumentów. W przeciwieństwie do dostawcy dokumentów usługi iCloud, który automatycznie zapisuje zabezpieczenia i zakładki w kontenerze aplikacji, rozszerzenia dostawcy dokumentów nie są częścią systemu referencyjnego dokumentów.

Na przykład: w ustawieniu Enterprise, które udostępnia własny bezpieczny magazyn danych w całej firmie, administratorzy nie chcą, aby poufne informacje firmowe uzyskiwały dostęp do publicznych serwerów iCloud ani nie przetwarzały ich. W związku z tym nie można użyć wbudowanego systemu referencyjnego dokumentów.

System zakładek nadal może być używany i jest odpowiedzialny za poprawne przetwarzanie adresu URL zakładki i zwracanie zawartości dokumentu wskazywanego przez niego.

W celach bezpieczeństwa system iOS 8 ma warstwę izolacji, która utrwala informacje o tym, do której aplikacji ma dostęp do identyfikatora, w którym dostawcy plików. Należy zauważyć, że cały dostęp do plików jest kontrolowany przez tę warstwę izolacji.

Na poniższym diagramie przedstawiono przepływ danych podczas pracy z zakładkami i rozszerzeniem dostawcy dokumentów:

Ten diagram przedstawia przepływ danych podczas pracy z zakładkami i rozszerzeniem dostawcy dokumentów

Następuje następujący proces:

  1. Aplikacja ma wprowadzić tło i musi utrwalić jej stan. Wywołuje NSUrl metodę tworzenia zakładki do pliku w magazynie alternatywnym.
  2. NSUrl wywołuje rozszerzenie dostawcy plików, aby uzyskać trwały adres URL do dokumentu.
  3. Rozszerzenie dostawcy plików zwraca adres URL jako ciąg do .NSUrl
  4. Adres NSUrl URL jest dołączany do zakładki i zwraca go do aplikacji.
  5. Gdy aplikacja obudzi się w tle i musi przywrócić stan, przekazuje zakładkę do .NSUrl
  6. NSUrl wywołuje rozszerzenie dostawcy plików z adresem URL pliku.
  7. Dostawca rozszerzenia plików uzyskuje dostęp do pliku i zwraca lokalizację pliku na NSUrl .
  8. Lokalizacja pliku jest pakowana z informacjami o zabezpieczeniach i zwracana do aplikacji.

W tym miejscu aplikacja może uzyskać dostęp do pliku i pracować z nim w zwykły sposób.

Zapisywanie plików

W tej sekcji przedstawiono sposób działania zapisywania plików w lokalizacji alternatywnej za pomocą rozszerzenia dostawcy dokumentów. Aplikacja systemu iOS będzie używać koordynacji plików do zapisywania informacji na dysku wewnątrz kontenera aplikacji. Wkrótce po pomyślnym zapisaniu pliku rozszerzenie dostawcy plików zostanie powiadomione o zmianie.

W tym momencie rozszerzenie dostawcy plików może rozpocząć przekazywanie pliku do lokalizacji alternatywnej (lub oznaczyć plik jako zanieczyszczony i wymagający przekazania).

Tworzenie nowych rozszerzeń dostawcy dokumentów

Tworzenie nowych rozszerzeń dostawcy dokumentów wykracza poza zakres tego artykułu wprowadzającego. Te informacje są dostępne tutaj, aby pokazać, że na podstawie rozszerzeń załadowanych przez użytkownika na urządzeniu z systemem iOS aplikacja może mieć dostęp do lokalizacji przechowywania dokumentów poza lokalizacją usługi iCloud firmy Apple.

Deweloper powinien mieć świadomość tego faktu podczas korzystania z selektora dokumentów i pracy z dokumentami zewnętrznymi. Nie należy zakładać, że te dokumenty są hostowane w usłudze iCloud.

Aby uzyskać więcej informacji na temat tworzenia dostawcy magazynu lub rozszerzenia selektora dokumentów, zobacz dokument Wprowadzenie do rozszerzeń aplikacji.

Migrowanie do dysku w usłudze iCloud

W systemie iOS 8 użytkownicy mogą nadal korzystać z istniejącego systemu dokumentów w usłudze iCloud używanego w systemie iOS 7 (i wcześniejszych systemach) lub zdecydować się na migrację istniejących dokumentów do nowego mechanizmu usługi iCloud Drive.

W systemie Mac OS X Yosemite firma Apple nie zapewnia zgodności z poprzednimi wersjami, więc wszystkie dokumenty muszą być migrowane do usługi iCloud Drive lub nie będą już aktualizowane na urządzeniach.

Po przeprowadzeniu migracji konta użytkownika do usługi iCloud Drive tylko urządzenia korzystające z usługi iCloud Drive będą mogły propagować zmiany do dokumentów na tych urządzeniach.

Ważne

Deweloperzy powinni pamiętać, że nowe funkcje opisane w tym artykule są dostępne tylko wtedy, gdy konto użytkownika zostało zmigrowane do usługi iCloud Drive.

Podsumowanie

W tym artykule omówiono zmiany istniejących interfejsów API usługi iCloud wymaganych do obsługi usługi iCloud Drive i nowego kontrolera widoku selektora dokumentów. Omówiła koordynację plików i dlaczego jest ona ważna podczas pracy z dokumentami opartymi na chmurze. Obejmowała ona konfigurację wymaganą do włączenia dokumentów opartych na chmurze w aplikacji platformy Xamarin.iOS i biorąc pod uwagę wprowadzenie do pracy z dokumentami spoza kontenera aplikacji aplikacji przy użyciu kontrolera widoku selektora dokumentów.

Ponadto w tym artykule krótko opisano rozszerzenia dostawcy dokumentów i dlaczego deweloper powinien być świadomy ich podczas pisania aplikacji, które mogą obsługiwać dokumenty oparte na chmurze.