تمكين المزامنة دون اتصال مع تطبيقات 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

MS_TableOperations سمات الجدول

السمة النوع
المعرف العدد الصحيح 64
معرف العنصر سلسلة
خصائص بيانات ثنائية
طاولتنا سلسلة
tableKind عدد صحيح 16

MS_TableOperationErrors

MS_TableOperationErrors سمات الجدول

السمة النوع
المعرف سلسلة
operationId العدد الصحيح 64
خصائص بيانات ثنائية
tableKind العدد الصحيح 16

MS_TableConfig

السمة النوع
المعرف سلسلة
المفتاح سلسلة
keyType العدد الصحيح 64
طاولتنا سلسلة
القيمة سلسلة

جدول البيانات

TodoItem

السمة النوع ملاحظة
المعرف سلسلة، تم وضع علامة مطلوب عليها المفتاح الأساسي في المخزن البعيد
كامله منطقي حقل عنصر المهام
نص سلسلة حقل عنصر المهام
إنشاء قاعدة بيانات التاريخ (اختياري) الخرائط لإنشاء خاصية النظام
التحديثات التاريخ (اختياري) تعيين إلى خاصية نظام updatedAt
version سلسلة (اختياري) يستخدم للكشف عن التعارضات، يعين إلى إصدار

تغيير سلوك المزامنة للتطبيق

في هذا القسم، يمكنك تعديل التطبيق بحيث لا تتم مزامنته عند بدء تشغيل التطبيق أو عند إدراج العناصر وتحديثها. تتم مزامنته فقط عند تنفيذ زر إيماءة التحديث.

Objective-C:

  1. في QSTodoListViewController.m، قم بتغيير طريقة viewDidLoad لإزالة الاستدعاء إلى [self refresh] في نهاية الأسلوب. الآن لم تتم مزامنة البيانات مع الخادم على بدء التطبيق. بدلا من ذلك، تتم مزامنتها مع محتويات المتجر المحلي.

  2. في QSTodoService.m، قم بتعديل تعريف addItem بحيث لا تتم مزامنته بعد إدراج العنصر. self syncData أزل الكتلة واستبدلها بما يلي:

    if (completion != nil) {
        dispatch_async(dispatch_get_main_queue(), completion);
    }
    
  3. تعديل تعريف 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 غير صالح لمحاكاة سيناريو غير متصل. عند إضافة عناصر بيانات، يتم الاحتفاظ بها في مخزن البيانات الأساسية المحلي، ولكن لا تتم مزامنتها مع النهاية الخلفية لتطبيق الأجهزة المحمولة.

  1. غير عنوان 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")
    
  2. إضافة بعض عناصر المهام. قم بإنهاء المحاكي (أو أغلق التطبيق قسرا)، ثم أعد تشغيله. تحقق من استمرار التغييرات.

  3. عرض محتويات جدول TodoItem البعيد:

    • للحصول على Node.js الخلفية، انتقل إلى مدخل Microsoft Azure ، وفي النهاية الخلفية لتطبيق الأجهزة المحمولة، انقر فوق Easy Tables>TodoItem.
    • بالنسبة لواجهة .NET الخلفية، استخدم إما أداة SQL، مثل SQL Server Management Studio، أو عميل REST، مثل Fiddler أو Postman.
  4. تحقق من عدم مزامنة العناصر الجديدة مع الخادم.

  5. قم بتغيير عنوان URL مرة أخرى إلى عنوان URL الصحيح في QSTodoService.m، وأعد تشغيل التطبيق.

  6. قم بتنفيذ إيماءة التحديث عن طريق سحب قائمة العناصر لأسفل.
    يتم عرض مغزل التقدم.

  7. عرض بيانات TodoItem مرة أخرى. يجب الآن عرض عناصر المهام الجديدة والمتغيرة.

الملخص

لدعم ميزة المزامنة دون اتصال، استخدمنا الواجهة MSSyncTable وتهيئتها MSClient.syncContext مع متجر محلي. في هذه الحالة، كان المتجر المحلي قاعدة بيانات تستند إلى البيانات الأساسية.

عند استخدام مخزن البيانات الأساسية المحلي، يجب تعريف عدة جداول بخصائص النظام الصحيحة.

تعمل عمليات الإنشاء والقراءة والتحديث والحذف العادية لتطبيقات الأجهزة المحمولة كما لو كان التطبيق لا يزال متصلا، ولكن تحدث جميع العمليات مقابل المتجر المحلي.

عندما قمنا بمزامنة المتجر المحلي مع الخادم، استخدمنا أسلوب MSSyncTable.pullWithQuery .

الموارد الإضافية