Sdílet prostřednictvím


Povolení offline synchronizace s mobilními aplikacemi pro iOS

Přehled

Tento kurz se zabývá offline synchronizací s funkcí Mobile Apps služby Azure App Service pro iOS. Díky offline synchronizaci mohou koncoví uživatelé pracovat s mobilní aplikací a zobrazovat, přidávat nebo upravovat data, i když nemají připojení k síti. Změny se ukládají v místní databázi. Jakmile je zařízení zase online, změny se synchronizují se vzdáleným back-endem.

Pokud se jedná o vaše první zkušenosti s Mobile Apps, měli byste nejprve dokončit kurz Vytvoření aplikace pro iOS. Pokud stažený projekt serveru rychlý start nepoužíváte, musíte do projektu přidat balíčky rozšíření pro přístup k datům. Další informace o balíčcích rozšíření serveru najdete v tématu Práce se sadou SDK back-endového serveru .NET pro azure Mobile Apps.

Další informace o funkci offline synchronizace najdete v tématu Offline synchronizace dat v mobilních aplikacích.

Kontrola kódu synchronizace klienta

Klientský projekt, který jste stáhli pro Vytvoření aplikace pro iOS, už obsahuje kód podporující offline synchronizaci pomocí místní databáze založené na Core Data. Tato část shrnuje, co už je součástí kódu kurzu. Koncepční přehled funkce najdete v tématu Offline synchronizace dat v mobilních aplikacích.

Pomocí funkce offline synchronizace dat Mobile Apps můžou koncoví uživatelé pracovat s místní databází i v případě, že je síť nepřístupná. Pokud chcete tyto funkce používat ve své aplikaci, inicializujte kontext synchronizace MSClient a odkažte na místní úložiště. Pak na tabulku odkazujete prostřednictvím rozhraní MSSyncTable.

V QSTodoService.m (Objective-C) nebo ToDoTableViewController.swift (Swift), všimněte si, že typ člena syncTable je MSSyncTable. Offline synchronizace používá toto rozhraní synchronizační tabulky místo MSTable. Při použití synchronizační tabulky všechny operace přejdou do místního úložiště a jsou synchronizovány pouze se vzdáleným back-endem s explicitními operacemi push a pull.

Pokud chcete získat odkaz na synchronizační tabulku, použijte metodu syncTableWithName na MSClient. Pokud chcete odebrat funkci offline synchronizace, použijte místo toho tableWithName.

Před provedením jakýchkoli operací tabulky je nutné inicializovat místní úložiště. Tady je příslušný kód:

  • Objective-C. Ve metodě QSTodoService.init:

    MSCoreDataStore *store = [[MSCoreDataStore alloc] initWithManagedObjectContext:context];
    self.client.syncContext = [[MSSyncContext alloc] initWithDelegate:nil dataSource:store callback:nil];
    
  • Swift. Ve metodě ToDoTableViewController.viewDidLoad:

    let client = MSClient(applicationURLString: "http:// ...") // URI of the Mobile App
    let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext!
    self.store = MSCoreDataStore(managedObjectContext: managedObjectContext)
    client.syncContext = MSSyncContext(delegate: nil, dataSource: self.store, callback: nil)
    

    Tato metoda vytvoří místní úložiště pomocí rozhraní MSCoreDataStore, které poskytuje sada Mobile Apps SDK. Alternativně můžete zadat jiné místní úložiště implementací protokolu MSSyncContextDataSource. Také první parametr MSSyncContext slouží k určení konfliktní obslužné rutiny. Protože jsme prošli nil, získáme výchozí obslužnou rutinu konfliktů, která selže při jakémkoli konfliktu.

Teď provedeme skutečnou operaci synchronizace a získáme data ze vzdáleného back-endu:

  • Objective-C. syncData nejprve odešle nové změny a potom zavolá pullData, aby získal data ze vzdáleného backendu. Metoda pullData zase získá nová data, která odpovídají dotazu:

    -(void)syncData:(QSCompletionBlock)completion
    {
         // Push all changes in the sync context, and then pull new data.
         [self.client.syncContext pushWithCompletion:^(NSError *error) {
             [self logErrorIfNotNil:error];
             [self pullData:completion];
         }];
    }
    
    -(void)pullData:(QSCompletionBlock)completion
    {
         MSQuery *query = [self.syncTable query];
    
         // Pulls data from the remote server into the local table.
         // We're pulling all items and filtering in the view.
         // Query ID is used for incremental sync.
         [self.syncTable pullWithQuery:query queryId:@"allTodoItems" completion:^(NSError *error) {
             [self logErrorIfNotNil:error];
    
             // Lets the caller know that we have finished.
             if (completion != nil) {
                 dispatch_async(dispatch_get_main_queue(), completion);
             }
         }];
    }
    
  • Swift:

    func onRefresh(sender: UIRefreshControl!) {
        UIApplication.sharedApplication().networkActivityIndicatorVisible = true
    
        self.table!.pullWithQuery(self.table?.query(), queryId: "AllRecords") {
            (error) -> Void in
    
            UIApplication.sharedApplication().networkActivityIndicatorVisible = false
    
            if error != nil {
                // A real application would handle various errors like network conditions,
                // server conflicts, etc. via the MSSyncContextDelegate
                print("Error: \(error!.description)")
    
                // We will discard our changes and keep the server's copy for simplicity
                if let opErrors = error!.userInfo[MSErrorPushResultKey] as? Array<MSTableOperationError> {
                    for opError in opErrors {
                        print("Attempted operation to item \(opError.itemId)")
                        if (opError.operation == .Insert || opError.operation == .Delete) {
                            print("Insert/Delete, failed discarding changes")
                            opError.cancelOperationAndDiscardItemWithCompletion(nil)
                        } else {
                            print("Update failed, reverting to server's copy")
                            opError.cancelOperationAndUpdateItem(opError.serverItem!, completion: nil)
                        }
                    }
                }
            }
            self.refreshControl?.endRefreshing()
        }
    }
    

Ve verzi Objective-C v syncDatanejprve v synchronizačním kontextu zavoláme pushWithCompletion. Tato metoda je členem MSSyncContext (nikoli samotné synchronizační tabulky), protože posouvá změny přes všechny tabulky. Na server se odesílají jenom záznamy, které byly upraveny nějakým způsobem (prostřednictvím operací CUD). Potom je volána pomocná funkce pullData, která následně zavolá MSSyncTable.pullWithQuery k načtení vzdálených dat a jejich uložení do místní databáze.

Ve verzi Swift, protože push operace nebyla nezbytně nutná, nedochází k žádnému volání pushWithCompletion. Pokud v kontextu synchronizace pro tabulku, která provádí operaci odesílání, čekají nějaké změny, operace přijetí vždy nejprve provede odeslání. Pokud ale máte více než jednu synchronizační tabulku, je nejlepší explicitně volat operaci push, abyste zajistili, že vše bude konzistentní napříč souvisejícími tabulkami.

Ve verzích Objective-C i Swift můžete k filtrování záznamů, které chcete načíst, použít metodu pullWithQuery. V tomto příkladu dotaz načte všechny záznamy ve vzdálené TodoItem tabulce.

Druhý parametr pullWithQuery je ID dotazu, které se používá pro přírůstkovou synchronizaci. Přírůstková synchronizace načítá pouze záznamy, které byly změněny od poslední synchronizace, pomocí časového razítka UpdatedAt záznamu (označovaného jako updatedAt v místním úložišti.) ID dotazu by mělo být popisný řetězec, který je jedinečný pro každý logický dotaz v aplikaci. Pokud chcete zrušit přírůstkovou synchronizaci, předejte nil jako ID dotazu. Tento přístup může být potenciálně neefektivní, protože načte všechny záznamy při každém vyžádání.

Aplikace Objective-C se synchronizuje při úpravě nebo přidání dat, když uživatel provede gesto aktualizace a spustí se.

Aplikace Swift se synchronizuje, když uživatel provede gesto aktualizace a spustí se.

Vzhledem k tomu, že se aplikace synchronizuje při každé změně dat (Objective-C) nebo při každém spuštění aplikace (Objective-C a Swift), aplikace předpokládá, že je uživatel online. V další části aplikaci aktualizujete tak, aby uživatelé mohli upravovat, i když jsou offline.

Kontrola základního datového modelu

Pokud používáte offline úložiště Core Data, musíte definovat konkrétní tabulky a pole v datovém modelu. Ukázková aplikace už obsahuje datový model se správným formátem. V této části si tyto tabulky projdeme a ukážeme si, jak se používají.

Otevřete QSDataModel.xcdatamodeld. Čtyři tabulky jsou definované –tři, které sada SDK používá, a jednu, která se používá pro samotné položky to-do:

  • MS_TableOperations: Sleduje položky, které je potřeba synchronizovat se serverem.
  • MS_TableOperationErrors: Sleduje všechny chyby, ke kterým dochází během offline synchronizace.
  • MS_TableConfig: Sleduje čas poslední aktualizace při poslední operaci synchronizace pro všechny stahovací operace.
  • TodoItem: Ukládá položky to-do. Systémové sloupce createdAt, updatedAta verze jsou volitelné systémové vlastnosti.

Poznámka:

Sada Mobile Apps SDK si vyhrazuje názvy sloupců, které začínají "``". Nepoužívejte tuto předponu s jinými než systémovými sloupci. Jinak se názvy sloupců změní, když použijete vzdálený back-end.

Když použijete funkci offline synchronizace, definujte tři systémové tabulky a datovou tabulku.

Systémové tabulky

MS_TableOperations

atributy tabulky MS_TableOperations

Vlastnost Typ
identifikační číslo Integer 64
Identifikátor položky Řetězec
vlastnosti Binární data
stůl Řetězec
TableKind 16bitový integer

MS_OperaceTabulkyChyby

atributy tabulky MS_TableOperationErrors

Vlastnost Typ
identifikační číslo Řetězec
operationId Celé číslo 64
vlastnosti Binární data
TableKind 16bitové celé číslo

MS_TableConfig

Vlastnost Typ
identifikační číslo Řetězec
klíč Řetězec
typ klíče Integer 64
stůl Řetězec
hodnota Řetězec

Datová tabulka

todoItem

Vlastnost Typ Poznámka:
identifikační číslo Řetězec označený jako povinný Primární klíč ve vzdáleném úložišti
kompletní Booleovská logika Pole položky úkolu
Text Řetězec Pole položky úkolu
createdAt Datum (volitelné) Mapuje se na vlastnost systému createdAt
aktualizováno dne Datum (volitelné) Odpovídá systémové vlastnosti updatedAt
verze Řetězec (volitelné) Používá se k detekci konfliktů, mapuje se na verzi.

Změna chování synchronizace aplikace

V této části upravíte aplikaci tak, aby se nesynchronizuje při spuštění aplikace nebo při vkládání a aktualizaci položek. Synchronizuje se pouze při provedení gesta pro aktualizaci.

Objective-C:

  1. V QSTodoListViewController.mzměňte viewDidLoad metoda odebrání volání [self refresh] na konci metody. Data se teď nesynchronizují se serverem při spuštění aplikace. Místo toho se synchronizuje s obsahem místního úložiště.

  2. V QSTodoService.mupravte definici addItem tak, aby se po vložení položky nesynchronizuje. Odeberte blok self syncData a nahraďte ho následujícím kódem:

    if (completion != nil) {
        dispatch_async(dispatch_get_main_queue(), completion);
    }
    
  3. Upravte definici completeItem, jak jsme zmínili dříve. Odeberte blok pro self syncData a nahraďte ho následujícím kódem:

    if (completion != nil) {
        dispatch_async(dispatch_get_main_queue(), completion);
    }
    

Swift:

V viewDidLoad, v ToDoTableViewController.swift, okomentujte dva zde zobrazené řádky, aby se při spuštění aplikace zastavila synchronizace. V době psaní tohoto článku aplikace Swift Todo neaktualizuje službu, když někdo přidá nebo dokončí položku. Aktualizuje službu pouze při spuštění aplikace.

self.refreshControl?.beginRefreshing()
self.onRefresh(self.refreshControl)

Otestování aplikace

V této části se připojíte k neplatné adrese URL pro simulaci offline scénáře. Když přidáváte datové položky, ukládají se v místním úložišti základních dat, ale nesynchronizují se s back-endem mobilní aplikace.

  1. Změňte adresu URL mobilní aplikace v QSTodoService.m na neplatnou adresu URL a spusťte aplikaci znovu:

    Objective-C. V QSTodoService.m:

    self.client = [MSClient clientWithApplicationURLString:@"https://sitename.azurewebsites.net.fail"];
    

    Swift. V ToDoTableViewController.swift:

    let client = MSClient(applicationURLString: "https://sitename.azurewebsites.net.fail")
    
  2. Přidejte nějaké to-do položky. Ukončete simulátor (nebo vynuceně zavřete aplikaci) a restartujte ho. Ověřte, že vaše změny zůstávají zachovány.

  3. Zobrazte obsah tabulky vzdáleného TodoItem.

    • Pokud chcete Node.js back-end, přejděte na webu Azure Portal a v back-endu mobilní aplikace klikněte na Easy Tables>TodoItem.
    • Pro back-end .NET použijte buď nástroj SQL, například SQL Server Management Studio, nebo klienta REST, jako je Fiddler nebo Postman.
  4. Ověřte, že nové položky nebyly synchronizovány s serverem.

  5. Změňte adresu URL zpět na správnou adresu v QSTodoService.ma spusťte aplikaci znovu.

  6. Gesto aktualizace můžete provést tak, že stáhnete seznam položek.
    Zobrazí se číselník průběhu.

  7. Prohlédněte si znovu data TodoItem. Nové a změněné položky to-do by se teď měly zobrazit.

Shrnutí

K podpoře funkce offline synchronizace jsme použili rozhraní MSSyncTable a inicializovali MSClient.syncContext s místním úložištěm. V tomto případě bylo místní úložiště databází založenou na základních datech.

Pokud používáte místní úložiště základních dat, musíte definovat několik tabulek s správnými systémovými vlastnostmi.

Normální operace vytváření, čtení, aktualizace a odstranění (CRUD) pro mobilní aplikace fungují stejně, jako kdyby byla aplikace stále připojená, ale všechny operace probíhají v místním úložišti.

Když jsme synchronizovali místní úložiště se serverem, použili jsme metodu MSSyncTable.pullWithQuery.

Další zdroje informací