إطار عمل سريع مستوحى من جلسة WWDC 2015 المتقدمة. المعروفة سابقًا باسم العمليات ، التي طورتها Danthorpe مع الكثير من المساعدة من مجتمعنا الرائع.
| الموارد | أين تجده |
|---|---|
| فيديو الجلسة | مطور. apple.com |
| وثائق مرجعية قديمة ولكنها أكثر اكتمالا | docs.danthorpe.me/perations |
| تم تحديثها ولكن لم تتم الآن مستندات مرجعية كاملة | الإجراء. kit.run/development |
| دليل البرمجة | العمليات. README.IO |
يدعم الإجراءات جميع منصات Apple الحالية. الحد الأدنى من المتطلبات:
يدعم الإصدار الحالي الذي تم إصداره من الإجراءات (5.1.0) Swift 4.2+ و Xcode 10.1. فرع development سريع 5 و Xcode 10.2 متوافق.
الإجراءات هي إطار "متعدد الوحدات" (لا تهتم بأنه ، لقد صنعت ذلك للتو). ما أعنيه ، هو أن مشروع XCode يحتوي على أهداف/منتجات متعددة تنتج كل منها وحدة سريعة. بعض هذه الوحدات عبارة عن منصات متداخلة ، والبعض الآخر مخصص ، على سبيل المثال ProcedureKitNetwork مقابل ProcedureKitMobile .
انظر دليل إجراء التثبيت.
Procedure هو Foundation.Operation . إنه فئة مجردة يجب أن تكون فئة فرعية.
import ProcedureKit
class MyFirstProcedure : Procedure {
override func execute ( ) {
print ( " Hello World " )
finish ( )
}
}
let queue = ProcedureQueue ( )
let myProcedure = MyFirstProcedure ( )
queue . add ( procedure : myProcedure )النقاط الرئيسية هنا هي:
Procedure الفئة الفرعيةexecute ولكن لا تستدعي super.execute()finish() بعد الانتهاء من العمل ، أو إذا تم إلغاء الإجراء. يمكن القيام بذلك بشكل غير متزامن.ProcedureQueue . يتم إرفاق المراقبين بإجراء فئة Procedure . يتلقون عمليات الاسترجاعات عند حدوث أحداث دورة الحياة. أحداث دورة الحياة هي: هل أرفق ، سيتم تنفيذها ، نفذت ، DID Cancel ، ستضيف عملية جديدة ، وأضيف عملية جديدة ، وسوف تنتهي وينتهي .
يتم تعريف هذه الطرق بواسطة بروتوكول ، لذلك يمكن كتابة الفئات المخصصة لتتوافق مع أحداث متعددة. ومع ذلك ، توجد الطرق القائمة على الكتلة لإضافة المراقبين بشكل طبيعي. على سبيل المثال ، لمراقبة عندما ينتهي الإجراء:
myProcedure . addDidFinishBlockObserver { procedure , errors in
procedure . log . info ( message : " Yay! Finished! " )
} يوفر Framework أيضًا BackgroundObserver و TimeoutObserver و NetworkObserver .
انظر الويكي على [[المراقبين | المراقبين]] لمزيد من المعلومات.
يتم إرفاق الشروط بإجراء فئة Procedure . قبل أن يكون الإجراء جاهزًا لتنفيذه ، سيقوم بتقييم جميع ظروفه بشكل غير متزامن. في حالة فشل أي شرط ، ينتهي بخطأ بدلاً من التنفيذ. على سبيل المثال:
myProcedure . add ( condition : BlockCondition {
// procedure will execute if true
// procedure will be ignored if false
// procedure will fail if error is thrown
return trueOrFalse // or throw AnError()
}يمكن أن تكون الظروف حصرية بشكل متبادل. هذا أقرب إلى القفل الذي يحمل منع عمليات أخرى مع نفس الاستبعاد الذي يتم تنفيذه.
يوفر Framework الشروط التالية: AuthorizedFor ، BlockCondition ، و MutuallyExclusive ، NegatedCondition NoFailedDependenciesCondition ، و SilentCondition و UserConfirmationCondition (في الإجراءات storureKitMobile ).
انظر الويكي على [[الشروط | الشروط]] ، أو دليل البرمجة القديم على الشروط | لمزيد من المعلومات.
تمثل القدرة على قدرة التطبيق على الوصول إلى قدرات حساب الجهاز أو المستخدم ، أو من المحتمل أي نوع من الموارد المسورة. على سبيل المثال ، خدمات الموقع وحاويات مجموعة السحابة والتقويمات وما إلى ذلك أو خدمة ويب. يوفر CapabiltiyProtocol نموذجًا موحدًا لـ:
GetAuthorizationStatusProcedure ،AuthorizeCapabilityProcedureAuthorizedFor .على سبيل المثال:
import ProcedureKit
import ProcedureKitLocation
class DoSomethingWithLocation : Procedure {
override init ( ) {
super . init ( )
name = " Location Operation "
add ( condition : AuthorizedFor ( Capability . Location ( . whenInUse ) ) )
}
override func execute ( ) {
// do something with Location Services here
finish ( )
}
} يوفر الإجراءات القدرات التالية: Capability.CloudKit Capability.Location
في العمليات ، (نسخة سابقة من هذا الإطار) ، كانت هناك المزيد من الوظائف (التقويم ، والصحة ، والصور ، والكتاب ، وما إلى ذلك) ، وما زلنا نفكر في كيفية تقديمها في الإجراءات .
راجع الويكي على [[القدرات | القدرات]] ، أو دليل البرمجة القديم على القدرات لمزيد من المعلومات.
Procedure له وظائف التسجيل الداخلية الخاصة به المكشوفة عبر خاصية log :
class LogExample : Procedure {
override func execute ( ) {
log . info ( " Hello World! " )
finish ( )
}
}راجع دليل البرمجة لمزيد من المعلومات حول تسجيل ودعم أطر سجل الطرف الثالث.
في كثير من الأحيان ، ستحتاج الإجراءات إلى تبعيات من أجل التنفيذ. كما هو معتاد مع التطبيقات غير المتزامنة/الحدث ، قد لا تكون هذه التبعيات معروفة في وقت الخلق. بدلاً من ذلك ، يجب حقنها بعد تهيئة الإجراء ، ولكن قبل تنفيذها. يدعم الإجراءات هذا عبر مجموعة من البروتوكولات والأنواع التي تعمل معًا. نعتقد أن هذا النمط رائع ، لأنه يشجع تكوين إجراءات الغرض الصغير. يمكن أن تكون هذه أسهل في الاختبار وربما تمكين إعادة استخدام أكبر. سوف تجد حقن التبعية المستخدمة وتشجيعها خلال هذا الإطار.
على أي حال ، أولاً ، قد تكون القيمة جاهزة أو معلقة. على سبيل المثال ، عند تهيئة الإجراء ، قد لا يكون له كل تبعياته ، لذلك فهي في حالة معلقة. نأمل أن يصبحوا جاهزين بحلول الوقت الذي ينفذ فيه.
ثانياً ، إذا كان هناك إجراء يحصل على التبعية المطلوبة من خلال إجراء آخر ، فقد ينجح ، أو قد يفشل بخطأ. لذلك هناك نوع نتيجة بسيط يدعم هذا.
ثالثًا ، هناك بروتوكولات لتحديد خصائص input output .
InputProcedure يربط نوع Input . يمكن أن تتوافق الفئة الفرعية Procedure مع هذا للسماح بحقن التبعية. لاحظ أنه يتم دعم خاصية input واحدة فقط ، وبالتالي ، قم بإنشاء أنواع بنية وسيطة لاحتواء تبعيات متعددة. بالطبع ، خاصية input هي نوع قيمة معلق.
يعرض OutputProcedure النوع المرتبط Output عبر خاصية output الخاصة به ، وهو نوع نتيجة معلق.
جمع كل شيء معًا هو مجموعة من واجهات برمجة التطبيقات على InputProcedure التي تتيح تبعيات التسلسل معًا. مثله:
import ProcedureKitLocation
// This class is part of the framework, it
// conforms to OutputProcedure
let getLocation = UserLocationProcedure ( )
// Lets assume we've written this, it
// conforms to InputProcedure
let processLocation = ProcessUserLocation ( )
// This line sets up dependency & injection
// it automatically handles errors and cancellation
processLocation . injectResult ( from : getLocation )
// Still need to add both procedures to the queue
queue . add ( procedures : getLocation , processLocation ) في ما سبق ، من المفترض أن يكون نوع Input مطابقة لنوع Output ، في هذه الحالة ، CLLocation . ومع ذلك ، من الممكن أيضًا استخدام إغلاق لتدليك نوع الإخراج إلى نوع الإدخال المطلوب ، على سبيل المثال:
import ProcedureKitLocation
// This class is part of the framework, it
// conforms to OutputProcedure
let getLocation = UserLocationProcedure ( )
// Lets assume we've written this, it
// conforms to InputProcedure, and
// requires a CLLocationSpeed value
let processSpeed = ProcessUserSpeed ( )
// This line sets up dependency & injection
// it automatically handles errors and cancellation
// and the closure extracts the speed value
processLocation . injectResult ( from : getLocation ) { $0 . speed }
// Still need to add both procedures to the queue
queue . add ( procedures : getLocation , processLocation ) حسنًا ، ماذا حدث للتو؟ حسنًا ، يحتوي واجهة برمجة تطبيقات injectResult على متغير يقبل إغلاقًا زائد. يتلقى الإغلاق قيمة الإخراج ، ويجب إرجاع قيمة الإدخال (أو رمي خطأ). لذلك ، ستعيد { $0.speed } خاصية السرعة من مثيل CLLocation للمستخدم.
الشيء الرئيسي الذي يجب ملاحظته هنا هو أن هذا الإغلاق يعمل بشكل متزامن. لذلك ، من الأفضل عدم وضع أي شيء مرهقة عليه. إذا كنت بحاجة إلى القيام بتعيينات أكثر تعقيدًا للبيانات ، فتحقق من TransformProcedure و AsyncTransformProcedure .
راجع دليل البرمجة على نتائج حقن لمزيد من المعلومات.