Offline synchroniseren met mobiele iOS-apps inschakelen
Overzicht
In deze zelfstudie wordt offlinesynchronisatie behandeld met de functie Mobile Apps van Azure App Service voor iOS. Wanneer eindgebruikers offline synchroniseren, kunnen ze communiceren met een mobiele app om gegevens weer te geven, toe te voegen of te wijzigen, zelfs wanneer ze geen netwerkverbinding hebben. Wijzigingen worden opgeslagen in een lokale database. Nadat het apparaat weer online is, worden de wijzigingen gesynchroniseerd met de externe back-end.
Als dit uw eerste ervaring is met Mobile Apps, moet u eerst de zelfstudie Een iOS-app maken voltooien. Als u het gedownloade quickstartserverproject niet gebruikt, moet u de uitbreidingspakketten voor gegevenstoegang toevoegen aan uw project. Zie Work with the .NET backend server server SDK for Azure Mobile Apps (Werken met de .NET-back-endserver-SDK voor Azure Mobile Apps) voor meer informatie over serverextensiepakketten.
Zie Offline Data Sync in Mobile Apps voor meer informatie over de functie offlinesynchronisatie.
De synchronisatiecode van de client controleren
Het clientproject dat u hebt gedownload voor de zelfstudie Een iOS-app maken bevat al code die ondersteuning biedt voor offlinesynchronisatie met behulp van een lokale Core Data-database. In deze sectie wordt samengevat wat al in de zelfstudiecode is opgenomen. Zie Offline Data Sync in Mobile Apps voor een conceptueel overzicht van de functie.
Met de functie voor offlinegegevenssynchronisatie van Mobile Apps kunnen eindgebruikers communiceren met een lokale database, zelfs wanneer het netwerk niet toegankelijk is. Als u deze functies in uw app wilt gebruiken, initialiseert u de synchronisatiecontext van MSClient
een lokaal archief en verwijst u ernaar. Vervolgens verwijst u naar de tabel via de MSSyncTable-interface .
In QSTodoService.m (Objective-C) of ToDoTableViewController.swift (Swift) ziet u dat het type synchronisatietabelMSSyncTable is. Offlinesynchronisatie maakt gebruik van deze interface voor synchronisatietabellen in plaats van MSTable. Wanneer een synchronisatietabel wordt gebruikt, gaan alle bewerkingen naar het lokale archief en worden ze alleen gesynchroniseerd met de externe back-end met expliciete push- en pull-bewerkingen.
Als u een verwijzing naar een synchronisatietabel wilt ophalen, gebruikt u de methode syncTableWithName op MSClient
. Als u de functionaliteit voor offlinesynchronisatie wilt verwijderen, gebruikt u in plaats daarvan tableWithName .
Voordat tabelbewerkingen kunnen worden uitgevoerd, moet het lokale archief worden geïnitialiseerd. Dit is de relevante code:
Objective-C. In de methode QSTodoService.init :
MSCoreDataStore *store = [[MSCoreDataStore alloc] initWithManagedObjectContext:context]; self.client.syncContext = [[MSSyncContext alloc] initWithDelegate:nil dataSource:store callback:nil];
Swift. In de methode 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)
Met deze methode maakt u een lokaal archief met behulp van de
MSCoreDataStore
interface, die de Mobile Apps SDK biedt. U kunt ook een ander lokaal archief opgeven door hetMSSyncContextDataSource
protocol te implementeren. Ook wordt de eerste parameter van MSSyncContext gebruikt om een conflicthandler op te geven. Omdat we zijn geslaagdnil
, krijgen we de standaard conflicthandler, die mislukt bij een conflict.
Nu gaan we de werkelijke synchronisatiebewerking uitvoeren en gegevens ophalen uit de externe back-end:
Objective-C.
syncData
pusht eerst nieuwe wijzigingen en roept vervolgens pullData aan om gegevens op te halen uit de externe back-end. Op zijn beurt haalt de pullData-methode nieuwe gegevens op die overeenkomen met een query:-(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() } }
In de Objective-C-versie roepen syncData
we eerst pushWithCompletion aan in de synchronisatiecontext. Deze methode is lid van MSSyncContext
(en niet de synchronisatietabel zelf), omdat wijzigingen in alle tabellen worden gepusht. Alleen records die lokaal zijn gewijzigd (via CUD-bewerkingen) worden naar de server verzonden. Vervolgens wordt de helper pullData aangeroepen, die MSSyncTable.pullWithQuery aanroept om externe gegevens op te halen en op te slaan in de lokale database.
In de Swift-versie, omdat de pushbewerking niet strikt noodzakelijk was, is er geen aanroep voor pushWithCompletion. Als er wijzigingen in behandeling zijn in de synchronisatiecontext voor de tabel die een pushbewerking uitvoert, geeft pull altijd eerst een push uit. Als u echter meer dan één synchronisatietabel hebt, is het raadzaam om push expliciet aan te roepen om ervoor te zorgen dat alles consistent is in gerelateerde tabellen.
In de versies Objective-C en Swift kunt u de methode pullWithQuery gebruiken om een query op te geven om de records te filteren die u wilt ophalen. In dit voorbeeld haalt de query alle records in de externe TodoItem
tabel op.
De tweede parameter van pullWithQuery is een query-id die wordt gebruikt voor incrementele synchronisatie. Incrementele synchronisatie haalt alleen records op die zijn gewijzigd sinds de laatste synchronisatie, met behulp van het tijdstempel van de record UpdatedAt
(aangeroepen updatedAt
in het lokale archief.) De query-id moet een beschrijvende tekenreeks zijn die uniek is voor elke logische query in uw app. Als u zich wilt afmelden voor incrementele synchronisatie, geeft nil
u deze door als de query-id. Deze benadering kan mogelijk inefficiënt zijn, omdat alle records voor elke pull-bewerking worden opgehaald.
De Objective-C-app wordt gesynchroniseerd wanneer u gegevens wijzigt of toevoegt, wanneer een gebruiker het vernieuwingsbeweging uitvoert en bij het starten.
De Swift-app wordt gesynchroniseerd wanneer de gebruiker de vernieuwingsbeweging uitvoert en bij het starten.
Omdat de app wordt gesynchroniseerd wanneer gegevens worden gewijzigd (Objective-C) of wanneer de app wordt gestart (Objective-C en Swift), wordt ervan uitgegaan dat de gebruiker online is. In een latere sectie gaat u de app bijwerken, zodat gebruikers zelfs wanneer ze offline zijn, kunnen bewerken.
Het basisgegevensmodel controleren
Wanneer u het offlinearchief Core Data gebruikt, moet u bepaalde tabellen en velden in uw gegevensmodel definiëren. De voorbeeld-app bevat al een gegevensmodel met de juiste indeling. In deze sectie doorlopen we deze tabellen om te laten zien hoe ze worden gebruikt.
Open QSDataModel.xcdatamodeld. Vier tabellen zijn gedefinieerd: drie tabellen die worden gebruikt door de SDK en een die wordt gebruikt voor de takenitems zelf:
- MS_TableOperations: houdt de items bij die moeten worden gesynchroniseerd met de server.
- MS_TableOperationErrors: houdt eventuele fouten bij die optreden tijdens offlinesynchronisatie.
- MS_TableConfig: houdt de laatst bijgewerkte tijd bij voor de laatste synchronisatiebewerking voor alle pull-bewerkingen.
- Taakitem: slaat de taakitems op. De systeemkolommen createdAt, updatedAt en versie zijn optionele systeemeigenschappen.
Notitie
De Mobile Apps SDK reserveert kolomnamen die beginnen met '``'. Gebruik dit voorvoegsel niet met iets anders dan systeemkolommen. Anders worden de kolomnamen gewijzigd wanneer u de externe back-end gebruikt.
Wanneer u de functie offlinesynchronisatie gebruikt, definieert u de drie systeemtabellen en de gegevenstabel.
Systeemtabellen
MS_TableOperations
Kenmerk | Type |
---|---|
id | Geheel getal 64 |
itemId | Tekenreeks |
properties | Binaire gegevens |
tabel | Tekenreeks |
tableKind | Geheel getal 16 |
MS_TableOperationErrors
Kenmerk | Type |
---|---|
id | Tekenreeks |
operationId | Geheel getal 64 |
properties | Binaire gegevens |
tableKind | Geheel getal 16 |
MS_TableConfig
Kenmerk | Type |
---|---|
id | Tekenreeks |
sleutel | Tekenreeks |
Keytype | Geheel getal 64 |
tabel | Tekenreeks |
waarde | Tekenreeks |
Gegevenstabel
Taakitem
Kenmerk | Type | Notitie |
---|---|---|
id | Tekenreeks, gemarkeerd als vereist | Primaire sleutel in externe opslag |
voltooid | Booleaans | Takenitemveld |
tekst | Tekenreeks | Takenitemveld |
createdAt | Date | (optioneel) Wordt toegewezen aan de systeemeigenschap CreatedAt |
updatedAt | Date | (optioneel) Wordt toegewezen aan bijgewerkte SysteemeigenschapAt |
versie | Tekenreeks | (optioneel) Wordt gebruikt om conflicten te detecteren, wordt toegewezen aan versie |
Het synchronisatiegedrag van de app wijzigen
In deze sectie wijzigt u de app zodat deze niet wordt gesynchroniseerd bij het starten van de app of wanneer u items invoegt en bijwerkt. Deze wordt alleen gesynchroniseerd wanneer de knop Voor vernieuwen wordt uitgevoerd.
Objective-C:
Wijzig in QSTodoListViewController.m de viewDidLoad-methode om de aanroep aan het einde van de methode te
[self refresh]
verwijderen. De gegevens worden nu niet gesynchroniseerd met de server bij het starten van de app. In plaats daarvan wordt deze gesynchroniseerd met de inhoud van het lokale archief.Wijzig in QSTodoService.m de definitie
addItem
zodat deze niet wordt gesynchroniseerd nadat het item is ingevoegd. Verwijder hetself syncData
blok en vervang het door het volgende:if (completion != nil) { dispatch_async(dispatch_get_main_queue(), completion); }
Wijzig de definitie van
completeItem
zoals eerder vermeld. Verwijder het blok enself syncData
vervang het door het volgende:if (completion != nil) { dispatch_async(dispatch_get_main_queue(), completion); }
Swift:
In viewDidLoad
ToDoTableViewController.swift markeert u de twee regels die hier worden weergegeven om te stoppen met synchroniseren bij het starten van de app. Op het moment van schrijven werkt de Swift Todo-app de service niet bij wanneer iemand een item toevoegt of voltooit. De service wordt alleen bijgewerkt bij het starten van de app.
self.refreshControl?.beginRefreshing()
self.onRefresh(self.refreshControl)
De app testen
In deze sectie maakt u verbinding met een ongeldige URL om een offlinescenario te simuleren. Wanneer u gegevensitems toevoegt, worden ze bewaard in het lokale Core Data-archief, maar worden ze niet gesynchroniseerd met de back-end van de mobiele app.
Wijzig de URL van de mobiele app in QSTodoService.m in een ongeldige URL en voer de app opnieuw uit:
Objective-C. In QSTodoService.m:
self.client = [MSClient clientWithApplicationURLString:@"https://sitename.azurewebsites.net.fail"];
Swift. In ToDoTableViewController.swift:
let client = MSClient(applicationURLString: "https://sitename.azurewebsites.net.fail")
Voeg enkele takenitems toe. Sluit de simulator af (of sluit de app geforceerd) en start deze opnieuw. Controleer of uw wijzigingen behouden blijven.
De inhoud van de externe todoItem-tabel weergeven :
- Voor een Node.js back-end gaat u naar de Azure Portal en klikt u in de back-end van uw mobiele app op Easy Tables>TodoItem.
- Gebruik voor een .NET-back-end een SQL-hulpprogramma, zoals SQL Server Management Studio of een REST-client, zoals Fiddler of Postman.
Controleer of de nieuwe items niet zijn gesynchroniseerd met de server.
Wijzig de URL terug in de juiste url in QSTodoService.m en voer de app opnieuw uit.
Voer de vernieuwingsbeweging uit door de lijst met items omlaag te trekken.
Er wordt een voortgangs spinner weergegeven.Bekijk de TodoItem-gegevens opnieuw. De nieuwe en gewijzigde takenitems moeten nu worden weergegeven.
Samenvatting
Ter ondersteuning van de functie voor offlinesynchronisatie hebben we de MSSyncTable
interface gebruikt en geïnitialiseerd MSClient.syncContext
met een lokaal archief. In dit geval was het lokale archief een database op basis van kerngegevens.
Wanneer u een lokaal kerngegevensarchief gebruikt, moet u verschillende tabellen met de juiste systeemeigenschappen definiëren.
De normale cruD-bewerkingen (create, read, update en delete) voor mobiele apps werken alsof de app nog steeds is verbonden, maar alle bewerkingen worden uitgevoerd in de lokale store.
Toen we het lokale archief met de server hebben gesynchroniseerd, hebben we de methode MSSyncTable.pullWithQuery gebruikt.
Aanvullende resources
- Offlinegegevenssynchronisatie in mobiele apps
- Cloud Cover: Offlinesynchronisatie in Azure Mobile Services (de video gaat over Mobile Services, maar offlinesynchronisatie van Mobile Apps werkt op een vergelijkbare manier.)