Swift Framework, вдохновленная WWDC 2015 Advanced NSOperations Session. Ранее известный как операции , разработанные @Danthorpe с большой помощью от нашего фантастического сообщества.
| Ресурс | Где его найти |
|---|---|
| Сеанс видео | Developer.apple.com |
| Старая, но более полная справочная документация | docs.danthorpe.me/operations |
| Обновленные, но еще не полные справочные документы | Процедура.kit.run/Development |
| Руководство по программированию | Operations.readme.io |
ProcecureKit поддерживает все текущие платформы Apple. Минимальные требования:
Текущая выпущенная версия ProcecureKit (5.1.0) поддерживает Swift 4.2+ и Xcode 10.1. Ветвь development Swift 5 и Xcode 10.2 совместима.
ProcecureKit -это «мультимодульная» структура (не беспокойтесь о том, чтобы Googling, я только что сделал это). Я имею в виду, что проект XCode имеет несколько целей/продуктов, каждый из которых производит модуль Swift. Некоторые из этих модулей являются кроссплатформенными, другие выделены, например, 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 . Они получают обратные вызовы, когда происходят события жизненного цикла. События Lifecycle: Do Dinted , выполнит , выполнит , выполнял, отменил , добавит новую работу , добавила новую работу , закончится и закончил .
Эти методы определяются протоколом, поэтому пользовательские классы могут быть записаны в соответствии с несколькими событиями. Однако существуют методы на основе блоков, чтобы добавить наблюдателей более естественно. Например, чтобы наблюдать, когда процедура завершается:
myProcedure . addDidFinishBlockObserver { procedure , errors in
procedure . log . info ( message : " Yay! Finished! " )
} Фреймворк также предоставляет 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()
}Условия могут быть взаимоисключающими. Это похоже на то, что блокировка удерживается, предотвращая другие операции с таким же исключением.
Структура содержит следующие условия: AuthorizedFor , BlockCondition , MutuallyExclusive , NegatedCondition , NoFailedDependenciesCondition , SilentCondition и UserConfirmationCondition (в ProcusureKitMobile ).
См. Вики на [[Условия | Условия]], или Старое руководство по программированию в условиях | Для получения дополнительной информации.
Возможность представляет собой возможность приложения получить доступ к устройствам или способностям к ответственности пользователя или, возможно, любого вида ограниченного ресурса. Например, службы местоположения, контейнеры облачных наборов, календари и т. Д. или веб -сервис. 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 ( )
}
} ProcecureKit предоставляет следующие возможности: Capability.CloudKit и Capability.Location .
В операциях (предыдущая версия этой структуры) существовало больше функциональности (календарь, здоровье, фотографии, адресная книга и т. Д.), И мы все еще рассматриваем, как их предложить в ProcusureKit .
См. Вики на [[возможности | Возможности]], или старое руководство по программированию по возможностям для получения дополнительной информации.
Procedure имеет свои собственные функции внутренней ведения журнала, обнаруженная с помощью свойства log :
class LogExample : Procedure {
override func execute ( ) {
log . info ( " Hello World! " )
finish ( )
}
}См. Руководство по программированию для получения дополнительной информации о журнале и поддержке сторонних фреймворков журнала.
Часто процедурам нуждаются в зависимости, чтобы выполнить. Как типично при асинхронных/на основе событий приложений, эти зависимости могут не быть известны во время создания. Вместо этого они должны быть введены после инициализации процедуры, но прежде чем она будет выполнена. ProcecureKit поддерживает это через набор протоколов и типов, которые работают вместе. Мы думаем, что этот шаблон велик, так как он поощряет состав небольших целевых процедур. Это может быть легче проверить и потенциально обеспечить более широкое повторное использование. Вы найдете инъекцию зависимостей, используемые и поощряемые на протяжении всей этой структуры.
В любом случае, во -первых, значение может быть готово или ожидается. Например, когда процедура инициализирована, она может не иметь всех ее зависимостей, поэтому они находятся в ожидаемом состоянии. Надеюсь, они станут готовыми к тому времени, когда он исполняется.
Во -вторых, если процедура приобретает зависимость, требуемую другой процедурой, она может быть успешной, или она может потерпеть неудачу с ошибкой. Поэтому существует простой тип результата , который поддерживает это.
В -третьих, существуют протоколы для определения input и output свойств.
InputProcedure связывает тип Input . Подкласс Procedure может соответствовать этому, чтобы обеспечить инъекцию зависимости. Обратите внимание, что только одно input свойство поддерживается, поэтому создает промежуточные типы структуры для содержания нескольких зависимостей. Конечно, input свойство является ожидающим типом значения.
OutputProcedure выявляет Output , через его output свойство, которое является ожидающим типом результата.
Собрать все это вместе - это набор API на 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 API есть вариант, который принимает следующий закрытие. Закрытие получает выходное значение и должно вернуть входное значение (или бросить ошибку). Таким образом, { $0.speed } вернет свойство Speed из экземпляра CLLocation пользователя.
Ключевой вещью здесь является то, что это закрытие работает синхронно. Таким образом, лучше не наложить на это ничего обременительного. Если вам нужно сделать более сложные сопоставления данных, ознакомьтесь с TransformProcedure и AsyncTransformProcedure .
См. Руководство по программированию по результатам инъекции для получения дополнительной информации.