Dela via


Aktivera offlinesynkronisering med iOS-mobilappar

Översikt

I den här självstudien beskrivs offlinesynkronisering med mobile apps-funktionen i Azure App Service för iOS. Med offlinesynkronisering kan slutanvändarna interagera med en mobilapp för att visa, lägga till eller ändra data, även om de inte har någon nätverksanslutning. Ändringar lagras i en lokal databas. När enheten är online igen synkroniseras ändringarna med fjärrserverdelen.

Om det här är din första upplevelse av Mobile Apps bör du först slutföra självstudien Skapa en iOS-app. Om du inte använder det nedladdade snabbstartsserverprojektet måste du lägga till paketen för dataåtkomsttillägg i projektet. Mer information om servertilläggspaket finns i Work with the .NET backend server SDK for Azure Mobile Apps.

Mer information om funktionen för offlinesynkronisering finns i Offline datasynkronisering i mobilappar.

Granska koden för klientsynkronisering

Klientprojektet som du laddade ned för självstudien Skapa en iOS-app innehåller redan kod som stöder offlinesynkronisering med hjälp av en lokal Core Data-baserad databas. Det här avsnittet sammanfattar vad som redan ingår i självstudiekoden. En konceptuell översikt över funktionen finns i Offline datasynkronisering i Mobilappar.

Med hjälp av funktionen för datasynkronisering offline i Mobile Apps kan slutanvändarna interagera med en lokal databas även när nätverket är otillgängligt. Om du vill använda de här funktionerna i din app initierar du synkroniseringskontexten för MSClient och refererar till en lokal lagring. Sedan refererar du till tabellen via MSSyncTable-gränssnittet .

Observera att typen av medlemssynkroniseringstabell är MSSyncTable i QSTodoService.m (Objective-C) eller ToDoTableViewController.swift (Swift). Offlinesynkronisering använder det här synkroniseringstabellgränssnittet i stället för MSTable. När en synkroniseringstabell används går alla åtgärder till det lokala lagret och synkroniseras endast med fjärränden via explicita push- och pull-åtgärder.

Om du vill hämta en referens till en synkroniseringstabell använder du metoden syncTableWithNameMSClient. Om du vill ta bort funktionen för offlinesynkronisering använder du tableWithName i stället.

Innan några tabellåtgärder kan utföras måste det lokala lagret initieras. Här är relevant kod:

  • Objective-C. I metoden QSTodoService.init :

    MSCoreDataStore *store = [[MSCoreDataStore alloc] initWithManagedObjectContext:context];
    self.client.syncContext = [[MSSyncContext alloc] initWithDelegate:nil dataSource:store callback:nil];
    
  • Swift. I metoden 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)
    

    Den här metoden skapar ett lokalt arkiv med hjälp av gränssnittet MSCoreDataStore, som Mobile Apps SDK tillhandahåller. Du kan också ange en annan lokal butik genom att implementera protokollet MSSyncContextDataSource. Den första parametern i MSSyncContext används också för att ange en konflikthanterare. Eftersom vi har använt nil får vi standardkonfliktshanteraren, som misslyckas vid varje konflikt.

Nu ska vi utföra den faktiska synkroniseringsåtgärden och hämta data från fjärrserverdelen:

  • Objective-C. syncData skickar först nya ändringar och anropar sedan pullData för att hämta data från fjärrserverdelen. PullData-metoden hämtar i sin tur nya data som matchar en fråga:

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

I den Objective-C versionen i syncDataanropar vi först pushWithCompletion i synkroniseringskontexten. Den här metoden är medlem i MSSyncContext (och inte själva synkroniseringstabellen) eftersom den skickar ändringar i alla tabeller. Endast poster som har ändrats på något sätt lokalt (via CUD-åtgärder) skickas till server. Sedan anropas hjälpverktyget pullData , som anropar MSSyncTable.pullWithQuery för att hämta fjärrdata och lagra dem i den lokala databasen.

Eftersom push-åtgärden inte var absolut nödvändig i Swift-versionen finns det inget anrop till pushWithCompletion. Om det finns ändringar som väntar i synkroniseringskontexten för tabellen som utför en push-åtgärd, utfärdar pull alltid en push först. Men om du har fler än en synkroniseringstabell är det bäst att uttryckligen anropa push för att säkerställa att allt är konsekvent mellan relaterade tabeller.

I både Objective-C- och Swift-versionerna kan du använda metoden pullWithQuery för att ange en fråga för att filtrera de poster som du vill hämta. I det här exemplet hämtar frågan alla poster i fjärrtabellen TodoItem .

Den andra parametern för pullWithQuery är ett fråge-ID som används för inkrementell synkronisering. Inkrementell synkronisering hämtar endast poster som har ändrats sedan den senaste synkroniseringen med postens tidsstämpel (anropas UpdatedAtupdatedAt i det lokala arkivet.) Fråge-ID:t ska vara en beskrivande sträng som är unik för varje logisk fråga i din app. Om du vill välja bort inkrementell synkronisering skickar nil du som fråge-ID. Den här metoden kan vara mindre effektiv eftersom den hämtar alla poster vid varje datahämtning.

Den Objective-C appen synkroniseras när du ändrar eller lägger till data, när en användare utför uppdateringsgesten och vid start.

Swift-appen synkroniseras när användaren utför uppdateringsgesten och vid start.

Eftersom appen synkroniseras när data ändras (Objective-C) eller när appen startar (Objective-C och Swift), förutsätter appen att användaren är online. I ett senare avsnitt uppdaterar du appen så att användarna kan redigera även när de är offline.

Granska Core Data-modellen

När du använder Core Data Offline Store måste du definiera specifika tabeller och fält i datamodellen. Exempelappen innehåller redan en datamodell med rätt format. I det här avsnittet går vi igenom de här tabellerna för att visa hur de används.

Öppna QSDataModel.xcdatamodeld. Fyra tabeller definieras – tre som används av SDK:t och en som används för själva to-do objekten:

  • MS_TableOperations: Spårar de objekt som måste synkroniseras med servern.
  • MS_TableOperationErrors: Spårar eventuella fel som inträffar under offlinesynkronisering.
  • MS_TableConfig: Spårar den senaste uppdaterade tiden för den senaste synkroniseringsåtgärden för alla pull-åtgärder.
  • TodoItem: Lagrar att göra-poster. Systemkolumnerna createdAt, updatedAt och version är valfria systemegenskaper.

Anmärkning

Mobile Apps SDK reserverar kolumnnamn som börjar med "``". Använd inte det här prefixet med något annat än systemkolumner. Annars ändras kolumnnamnen när du använder fjärrserverdelen.

När du använder funktionen för offlinesynkronisering definierar du de tre systemtabellerna och datatabellen.

Systemtabeller

MS_TableOperations

MS_TableOperations tabellattribut

Attribut Typ
Id-nummer Heltal 64
Artikel-ID Sträng
egenskaper Binära data
bord Sträng
tableKind Heltal 16

MS_TableOperationErrors

MS_TableOperationErrors tabellattribut

Attribut Typ
Id-nummer Sträng
operationId Heltal 64
egenskaper Binära data
tableKind Heltal 16

MS_TableConfig

Attribut Typ
Id-nummer Sträng
nyckel Sträng
nyckeltyp Heltal 64
bord Sträng
värde Sträng

Datatabell

TodoItem

Attribut Typ Anmärkning
Id-nummer Sträng, markerad som obligatorisk Primärnyckel i fjärrlagring
komplett Boolean Att göra-objektfält
texten Sträng Att göra-objektfält
createdAt Datum (valfritt) Kartlägger till createdAt systemegenskap
uppdaterad vid Datum (valfritt) Mapper till updatedAt Systemegenskap
version Sträng (valfritt) Används för att identifiera konflikter, korrelerar med version

Ändra synkroniseringsbeteendet för appen

I det här avsnittet ändrar du appen så att den inte synkroniseras vid appstart eller när du infogar och uppdaterar objekt. Den synkroniseras endast när uppdateringsgesten utförs.

Objective-C:

  1. I QSTodoListViewController.m ändrar du metoden viewDidLoad för att ta bort anropet till [self refresh] i slutet av metoden. Nu synkroniseras inte data med servern vid appstart. I stället synkroniseras den med innehållet i den lokala butiken.

  2. I QSTodoService.m ändrar du definitionen för addItem så att den inte synkroniseras när objektet har infogats. self syncData Ta bort blocket och ersätt det med följande:

    if (completion != nil) {
        dispatch_async(dispatch_get_main_queue(), completion);
    }
    
  3. Ändra definitionen av completeItem som nämnts tidigare. Ta bort blocket för self syncData och ersätt det med följande:

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

Swift:

I viewDidLoad, i ToDoTableViewController.swift, kommenterar du ut de två raderna som visas här för att sluta synkronisera vid appstart. När detta skrivs uppdaterar inte Swift Todo-appen tjänsten när någon lägger till eller slutför ett objekt. Tjänsten uppdateras endast vid start av appen.

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

Testa appen

I det här avsnittet ansluter du till en ogiltig URL för att simulera ett offlinescenario. När du lägger till dataobjekt lagras de i det lokala Core Data Store, men de synkroniseras inte med mobilappens serverdel.

  1. Ändra mobilappens URL i QSTodoService.m till en ogiltig URL och kör appen igen:

    Objective-C. I QSTodoService.m:

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

    Swift. Inne i "ToDoTableViewController.swift":

    let client = MSClient(applicationURLString: "https://sitename.azurewebsites.net.fail")
    
  2. Lägg till några to-do objekt. Avsluta simulatorn (eller tvinga appen att stängas), och starta sedan om den. Kontrollera att ändringarna sparas.

  3. Visa innehållet i den fjärranslutna TodoItem-tabellen :

    • För en Node.js serverdel går du till Azure-portalen och i mobilappens serverdel klickar du på Enkla tabeller>TodoItem.
    • För en .NET-serverdel använder du antingen ett SQL-verktyg, till exempel SQL Server Management Studio eller en REST-klient, till exempel Fiddler eller Postman.
  4. Kontrollera att de nya objekten inte har synkroniserats med servern.

  5. Ändra tillbaka URL:en till rätt i QSTodoService.m och kör appen igen.

  6. Utför uppdateringsgesten genom att dra ner listan med objekt.
    En förloppsindikator visas.

  7. Visa TodoItem-data igen. De nya och ändrade to-do objekten ska nu visas.

Sammanfattning

För att stödja funktionen för offlinesynkronisering använde vi gränssnittet MSSyncTable och initierade MSClient.syncContext med en lokal butik. I det här fallet var den lokala butiken en Core Data-baserad databas.

När du använder ett lokalt Core Data-arkiv måste du definiera flera tabeller med rätt systemegenskaper.

De normala CRUD-åtgärderna för att skapa, läsa, uppdatera och ta bort i mobilappar fungerar som om appen fortfarande är ansluten, men alla åtgärder sker mot den lokala lagringen.

När vi synkroniserade det lokala arkivet med servern använde vi metoden MSSyncTable.pullWithQuery .

Ytterligare resurser