تمكين المزامنة دون اتصال مع تطبيقات iOS للأجهزة المحمولة
نظرة عامة
يغطي هذا البرنامج التعليمي المزامنة دون اتصال مع ميزة تطبيقات الأجهزة المحمولة في Azure App Service لنظام التشغيل iOS. باستخدام المزامنة دون اتصال، يمكن للمستخدمين التفاعل مع تطبيق الأجهزة المحمولة لعرض البيانات أو إضافتها أو تعديلها، حتى عندما لا يكون لديهم اتصال بالشبكة. يتم تخزين التغييرات في قاعدة بيانات محلية. بعد عودة الجهاز إلى الاتصال بالإنترنت، تتم مزامنة التغييرات مع الواجهة الخلفية البعيدة.
إذا كانت هذه هي تجربتك الأولى مع تطبيقات الأجهزة المحمولة، فيجب عليك أولا إكمال البرنامج التعليمي إنشاء تطبيق iOS. إذا لم تستخدم مشروع خادم البدء السريع الذي تم تنزيله، يجب إضافة حزم ملحقات الوصول إلى البيانات إلى مشروعك. لمزيد من المعلومات حول حزم ملحق الخادم، راجع العمل مع .NET backend server SDK لتطبيقات Azure Mobile.
لمعرفة المزيد حول ميزة المزامنة دون اتصال، راجع مزامنة البيانات دون اتصال في تطبيقات الأجهزة المحمولة.
مراجعة التعليمات البرمجية لمزامنة العميل
يحتوي مشروع العميل الذي قمت بتنزيله لبرنامج تعليمي إنشاء تطبيق iOS بالفعل على تعليمات برمجية تدعم المزامنة دون اتصال باستخدام قاعدة بيانات أساسية محلية تستند إلى البيانات الأساسية. يلخص هذا القسم ما تم تضمينه بالفعل في التعليمات البرمجية البرنامج التعليمي. للحصول على نظرة عامة تصورية حول الميزة، راجع مزامنة البيانات دون اتصال في تطبيقات الأجهزة المحمولة.
باستخدام ميزة مزامنة البيانات دون اتصال لتطبيقات الأجهزة المحمولة، يمكن للمستخدمين التفاعل مع قاعدة بيانات محلية حتى عندما يتعذر الوصول إلى الشبكة. لاستخدام هذه الميزات في تطبيقك، يمكنك تهيئة سياق المزامنة للمتجر MSClient
المحلي والإشارة إليه. ثم يمكنك الرجوع إلى الجدول الخاص بك من خلال واجهة MSSyncTable .
في QSTodoService.m (Objective-C) أو ToDoTableViewController.swift (Swift)، لاحظ أن نوع مزامنة العضو هو MSSyncTable. تستخدم المزامنة دون اتصال واجهة جدول المزامنة هذه بدلا من MSTable. عند استخدام جدول مزامنة، تنتقل جميع العمليات إلى المتجر المحلي وتتم مزامنتها فقط مع الواجهة الخلفية البعيدة مع عمليات دفع وسحب صريحة.
للحصول على مرجع لجدول مزامنة، استخدم أسلوب syncTableWithName على MSClient
. لإزالة وظيفة المزامنة دون اتصال، استخدم tableWithName بدلا من ذلك.
قبل تنفيذ أي عمليات جدول، يجب تهيئة المتجر المحلي. فيما يلي التعليمات البرمجية ذات الصلة:
Objective-C. في أسلوب QSTodoService.init :
MSCoreDataStore *store = [[MSCoreDataStore alloc] initWithManagedObjectContext:context]; self.client.syncContext = [[MSSyncContext alloc] initWithDelegate:nil dataSource:store callback:nil];
سويفت. في أسلوب 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)
ينشئ هذا الأسلوب متجرا محليا باستخدام الواجهة
MSCoreDataStore
، والتي توفرها SDK لتطبيقات الأجهزة المحمولة. بدلا من ذلك، يمكنك توفير مخزن محلي مختلف عن طريق تنفيذMSSyncContextDataSource
البروتوكول. أيضا، يتم استخدام المعلمة الأولى من MSSyncContext لتحديد معالج تعارض. نظرا لأننا قمنا بتمريرnil
، نحصل على معالج التعارض الافتراضي، والذي يفشل في أي تعارض.
الآن، دعنا ننفذ عملية المزامنة الفعلية، ونحصل على البيانات من النهاية الخلفية البعيدة:
Objective-C.
syncData
يدفع أولا تغييرات جديدة ثم يستدعي pullData للحصول على البيانات من النهاية الخلفية البعيدة. بدوره، يحصل أسلوب pullData على بيانات جديدة تطابق استعلام:-(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() } }
في إصدار Objective-C، في syncData
، نستدعي أولا pushWithCompletion في سياق المزامنة. هذا الأسلوب عضو في MSSyncContext
(وليس جدول المزامنة نفسه) لأنه يدفع التغييرات عبر جميع الجداول. يتم إرسال السجلات التي تم تعديلها بطريقة ما محليا (من خلال عمليات CUD) فقط إلى الخادم. ثم يتم استدعاء بيانات المساعد pullData ، والتي تستدعي MSSyncTable.pullWithQuery لاسترداد البيانات البعيدة وتخزينها في قاعدة البيانات المحلية.
في إصدار Swift، لأن عملية الدفع لم تكن ضرورية تماما، لا يوجد استدعاء ل pushWithCompletion. إذا كانت هناك أي تغييرات معلقة في سياق المزامنة للجدول الذي يقوم بعملية دفع، فإن السحب دائما ما يصدر دفعة أولا. ومع ذلك، إذا كان لديك أكثر من جدول مزامنة واحد، فمن الأفضل استدعاء الدفع بشكل صريح للتأكد من أن كل شيء متناسق عبر الجداول ذات الصلة.
في كل من إصداري Objective-C وSwift، يمكنك استخدام أسلوب pullWithQuery لتحديد استعلام لتصفية السجلات التي تريد استردادها. في هذا المثال، يسترد الاستعلام كافة السجلات في الجدول البعيد TodoItem
.
المعلمة الثانية من pullWithQuery هي معرف استعلام يستخدم للمزامنة التزايدية. تسترد المزامنة التزايدية السجلات التي تم تعديلها منذ المزامنة الأخيرة فقط، باستخدام الطابع الزمني للسجل UpdatedAt
(يسمى updatedAt
في المتجر المحلي.) يجب أن يكون معرف الاستعلام سلسلة وصفية فريدة لكل استعلام منطقي في تطبيقك. لإلغاء الاشتراك في المزامنة التزايدية، مرر nil
كمعرف الاستعلام. يمكن أن يكون هذا الأسلوب غير فعال، لأنه يسترد جميع السجلات في كل عملية سحب.
تتم مزامنة تطبيق Objective-C عند تعديل البيانات أو إضافتها، وعندما يقوم المستخدم بتنفيذ إيماءة التحديث، وعند التشغيل.
تتم مزامنة تطبيق Swift عندما يقوم المستخدم بتنفيذ إيماءة التحديث وعند التشغيل.
نظرا لأن التطبيق يتزامن كلما تم تعديل البيانات (Objective-C) أو كلما بدأ التطبيق (Objective-C وSwift)، يفترض التطبيق أن المستخدم متصل بالإنترنت. في قسم لاحق، ستقوم بتحديث التطبيق بحيث يمكن للمستخدمين التحرير حتى عندما يكونون غير متصلين.
مراجعة نموذج البيانات الأساسية
عند استخدام مخزن البيانات الأساسية دون اتصال، يجب تحديد جداول وحقول معينة في نموذج البيانات. يتضمن نموذج التطبيق بالفعل نموذج بيانات بالتنسيق الصحيح. في هذا القسم، نستعرض هذه الجداول لإظهار كيفية استخدامها.
افتح QSDataModel.xcdatamodeld. يتم تعريف أربعة جداول -- ثلاثة تستخدمها SDK وواحدة تستخدم لعناصر المهام نفسها:
- MS_TableOperations: يتعقب العناصر التي تحتاج إلى مزامنة مع الخادم.
- MS_TableOperationErrors: يتعقب أي أخطاء تحدث أثناء المزامنة دون اتصال.
- MS_TableConfig: يتعقب آخر وقت تم تحديثه لعملية المزامنة الأخيرة لجميع عمليات السحب.
- TodoItem: يخزن عناصر المهام. أعمدة النظام التي تم إنشاؤهاAt و updatedAtوالإصدار هي خصائص نظام اختيارية.
ملاحظة
يحتفظ Mobile Apps SDK بأسماء الأعمدة التي تبدأ ب "``". لا تستخدم هذه البادئة مع أي شيء آخر غير أعمدة النظام. وإلا، يتم تعديل أسماء الأعمدة عند استخدام الواجهة الخلفية البعيدة.
عند استخدام ميزة المزامنة دون اتصال، حدد جداول النظام الثلاثة وجدول البيانات.
جداول النظام
MS_TableOperations
السمة | النوع |
---|---|
المعرف | العدد الصحيح 64 |
معرف العنصر | سلسلة |
خصائص | بيانات ثنائية |
طاولتنا | سلسلة |
tableKind | عدد صحيح 16 |
MS_TableOperationErrors
السمة | النوع |
---|---|
المعرف | سلسلة |
operationId | العدد الصحيح 64 |
خصائص | بيانات ثنائية |
tableKind | العدد الصحيح 16 |
MS_TableConfig
السمة | النوع |
---|---|
المعرف | سلسلة |
المفتاح | سلسلة |
keyType | العدد الصحيح 64 |
طاولتنا | سلسلة |
القيمة | سلسلة |
جدول البيانات
TodoItem
السمة | النوع | ملاحظة |
---|---|---|
المعرف | سلسلة، تم وضع علامة مطلوب عليها | المفتاح الأساسي في المخزن البعيد |
كامله | منطقي | حقل عنصر المهام |
نص | سلسلة | حقل عنصر المهام |
إنشاء قاعدة بيانات | التاريخ | (اختياري) الخرائط لإنشاء خاصية النظام |
التحديثات | التاريخ | (اختياري) تعيين إلى خاصية نظام updatedAt |
version | سلسلة | (اختياري) يستخدم للكشف عن التعارضات، يعين إلى إصدار |
تغيير سلوك المزامنة للتطبيق
في هذا القسم، يمكنك تعديل التطبيق بحيث لا تتم مزامنته عند بدء تشغيل التطبيق أو عند إدراج العناصر وتحديثها. تتم مزامنته فقط عند تنفيذ زر إيماءة التحديث.
Objective-C:
في QSTodoListViewController.m، قم بتغيير طريقة viewDidLoad لإزالة الاستدعاء إلى
[self refresh]
في نهاية الأسلوب. الآن لم تتم مزامنة البيانات مع الخادم على بدء التطبيق. بدلا من ذلك، تتم مزامنتها مع محتويات المتجر المحلي.في QSTodoService.m، قم بتعديل تعريف
addItem
بحيث لا تتم مزامنته بعد إدراج العنصر.self syncData
أزل الكتلة واستبدلها بما يلي:if (completion != nil) { dispatch_async(dispatch_get_main_queue(), completion); }
تعديل تعريف
completeItem
كما ذكر سابقا. قم بإزالة الكتلة لself syncData
واستبدلها بما يلي:if (completion != nil) { dispatch_async(dispatch_get_main_queue(), completion); }
Swift:
في viewDidLoad
، في ToDoTableViewController.swift، قم بالتعليق على السطرين الموضحين هنا، لإيقاف المزامنة عند بدء تشغيل التطبيق. في وقت كتابة هذا التقرير، لا يقوم تطبيق Swift Todo بتحديث الخدمة عند قيام شخص ما بإضافة عنصر أو إكماله. يقوم بتحديث الخدمة فقط عند بدء تشغيل التطبيق.
self.refreshControl?.beginRefreshing()
self.onRefresh(self.refreshControl)
اختبار التطبيق
في هذا القسم، يمكنك الاتصال بعنوان URL غير صالح لمحاكاة سيناريو غير متصل. عند إضافة عناصر بيانات، يتم الاحتفاظ بها في مخزن البيانات الأساسية المحلي، ولكن لا تتم مزامنتها مع النهاية الخلفية لتطبيق الأجهزة المحمولة.
غير عنوان URL لتطبيق الأجهزة المحمولة في QSTodoService.m إلى عنوان URL غير صالح، ثم قم بتشغيل التطبيق مرة أخرى:
Objective-C. في QSTodoService.m:
self.client = [MSClient clientWithApplicationURLString:@"https://sitename.azurewebsites.net.fail"];
سويفت. في ToDoTableViewController.swift:
let client = MSClient(applicationURLString: "https://sitename.azurewebsites.net.fail")
إضافة بعض عناصر المهام. قم بإنهاء المحاكي (أو أغلق التطبيق قسرا)، ثم أعد تشغيله. تحقق من استمرار التغييرات.
عرض محتويات جدول TodoItem البعيد:
- للحصول على Node.js الخلفية، انتقل إلى مدخل Microsoft Azure ، وفي النهاية الخلفية لتطبيق الأجهزة المحمولة، انقر فوق Easy Tables>TodoItem.
- بالنسبة لواجهة .NET الخلفية، استخدم إما أداة SQL، مثل SQL Server Management Studio، أو عميل REST، مثل Fiddler أو Postman.
تحقق من عدم مزامنة العناصر الجديدة مع الخادم.
قم بتغيير عنوان URL مرة أخرى إلى عنوان URL الصحيح في QSTodoService.m، وأعد تشغيل التطبيق.
قم بتنفيذ إيماءة التحديث عن طريق سحب قائمة العناصر لأسفل.
يتم عرض مغزل التقدم.عرض بيانات TodoItem مرة أخرى. يجب الآن عرض عناصر المهام الجديدة والمتغيرة.
الملخص
لدعم ميزة المزامنة دون اتصال، استخدمنا الواجهة MSSyncTable
وتهيئتها MSClient.syncContext
مع متجر محلي. في هذه الحالة، كان المتجر المحلي قاعدة بيانات تستند إلى البيانات الأساسية.
عند استخدام مخزن البيانات الأساسية المحلي، يجب تعريف عدة جداول بخصائص النظام الصحيحة.
تعمل عمليات الإنشاء والقراءة والتحديث والحذف العادية لتطبيقات الأجهزة المحمولة كما لو كان التطبيق لا يزال متصلا، ولكن تحدث جميع العمليات مقابل المتجر المحلي.
عندما قمنا بمزامنة المتجر المحلي مع الخادم، استخدمنا أسلوب MSSyncTable.pullWithQuery .
الموارد الإضافية
- مزامنة البيانات دون اتصال في تطبيقات الأجهزة المحمولة
- Cloud Cover: المزامنة دون اتصال في Azure Mobile Services (الفيديو يتعلق بخدمات الأجهزة المحمولة، ولكن تعمل مزامنة تطبيقات الأجهزة المحمولة دون اتصال بطريقة مماثلة.)