5.0.0
5.0.0
This is a rather long-awaited next major version of ProcedureKit.
Headline Changes
- Networking procedures no longer use an associated type for the
URLSession. InsteadSessionis a free-floating protocol. This makes general usage, subclassing and composing much simpler. - There is now a Core Data module
BlockProcedureAPI has changed.Procedureonly supports a singleErrorvalue, instead of[Error]- this has had some fairly wide reaching changes to APIs.- New built-in logger, which uses
os_logby default. - Changes to
UIProcedurein ProcedureKitMobile module.
Breaking Changes
-
[823]: Removes associated types from Network
Originally raised as an issue by @ericyanush in which I totally missed the point initially. But, after thinking about it more, made so much sense. Instead of having a generic
URLSessionTaskFactoryprotocol, where the various types of tasks were associated types, we now just have a non-genericNetworkSessionprotocol, to whichURLSessionconforms. The impact of this subtle change, is that what was once:NetworkDataProcedure<Session: URLSessionTaskFactory>is nowNetworkDataProcedure. In otherwords, no longer generic, and now super easy to use as that genericSessiondoesn't leak all over the place. -
[#875]: Refactored
BlockProcedureThere has been a long-standing wish for
BlockProcedureinstances to "receive themselves" in their block to allow for access to its logger etc. In v5, the following is all possible, see this comment:-
Simple synchronous block (existing functionality):
let block = BlockProcedure { print("Hello World") } -
Synchonous block, accessing the procedure inside the block:
let block = BlockProcedure { this in this.log.debug.message("Hello World") this.finish() }Note that here, the block is responsible for finishing itself - i.e. call
.finish()or.finish(with:)to finish the Procedure. Using this initializer, by default,BlockProcedurewill add aTimeoutObserverto itself, usingdefaultTimeoutIntervalwhich is set to 3 seconds. This can be modified if needed.BlockProcedure.defaultTimeoutInterval = 5 -
Asynchronous block with cancellation check,
AsyncBlockProcedureandCancellableBlockProcedureget deprecated warnings.let block = BlockProcedure { this in guard !this.isCancelled else { this.finish() } DispatchQueue.default.async { print("Hello world") this.finish() } } -
ResultProcedureas been re-written as a subclass ofBlockProcedure(previously, it was the superclass). Existing functionality has been maintained:let hello = ResultProcedure { "Hello World" }
-
-
[#851]: Errors
At WWDC18 I spent some time with some Swift engineers from Apple talking about framework design and error handling. The key take-away from these discussions was to increase clarity which reduces confusion, and makes intent clear.
This theme drove some significant changes. To increase clarity, each Procedure can only have a single
Error, because ultimately, how can a framework consumer "handle" an array ofErrorvalues over just a single one? I realised that the only reasonProcedurehas an[Error]property at all was fromGroupProcedurecollecting all of the errors from its children, yet the impact of this is felt throughout the codebase.This means, to finish a procedure with an error, use:
finish(with: .downloadFailedError) // this is a made up error typeObservers only receive a single error now:
procedure.addDidFinishBlockObserver { (this, error) in guard let error = error else { // there is an error, the block argument is Error? type return } // etc }Plus more API changes in
ProcedureandGroupProcedurewhich will result in deprecation warnings for framework consumers.For
GroupProcedureitself, it will now only set its own error to the first error received. However, to access the errors from child procedures, use the.childrenproperty. Something like:let errors = group.children.operationsAndProcedures.1.compactMap { $0.error } -
ProcedureKit has its own logging system, which has received an overhawl in v5. The changes are:
1. Now uses `os_log` instead of `print()` where available.2. Dedicated severity levels for caveman debugging & user event. See this comment. 3. Slight API change:
swift procedure.log.info.message("This is my debug message")previously, it was:swift procedure.log.info("This is my debug message")For module-wide settings:swift Log.enabled = true Log.severity = .debug // default is .warning Log.writer = CustomLogWriter() // See LogWriter protocol Log.formatter = CustomLogFormatter() // See LogFormatter protocol -
[#860]: Swift 3/4 API naming & conventions
@lukeredpath initially raised the issue in #796, that some APIs such as
add(condition: aCondition)did not Swift 3/4 API guidelines, and contributed to inconsistency within the framework. These have now been tidied up.
New Features & Improvements
-
[#830, #837]: Swift 4.1 & Xcode 9.3 support, (Xcode 10 is ready to go).
These changes take advantage of Swift 4.1 capabilities, such as synthesized
Equatableand conditional conformance. -
[#828, #833]: Result Injection & Binding
Result Injection conformance is added to
RepeatProcedure(and subclasses such asRetryProcedure&NetworkProcedure). This means the input can be set on the outRepeatProcedure, and this value will be set on every instance of the target procedure (assuming it also conforms toInputProcedure). This avoids having to jump through hoops like this.Additionally, a new binding API can be used, particularly with
GroupProceduresubclasses, so that the input of a child procedure is "bound" to that of the group itself, likewise, the output of the group is bound to a child. This makes it very easy to encapsulate a chain of procedures which use result injection into aGroupProceduresubclass. See the docs.
Notes
Thanks to everyone who has contributed to ProcedureKit - v5 has been quite a while in development. There is still quite a bit left to do on the documentation effort - but that will be ongoing for evermore.
Complete Diff
Final from Beta 2
ce3285eb377 [5.0.0]: Supports ProcedureKitCoreData via SPM 47eee7cb994 [5.0.0]: Sets the version to 5.0.0 b868c595d07 Refactors InsertManagedObjectsProcedure (#904) dcf57be331e Further fixes for CloudKit (#902) ccfe9babd93 Fixes issues with ResultProcedure init (#901) 2e8686c9ec0 Makes makeTimerSource public (#894) 234d0541f1e Fixes retain cycle due to strong self capture in inject result (#898) 2bf45aac793 Supports InputProcedure on DelayProcedure (#891)
Beta 2 from Beta 1
917a51fad18 [5.0.0.beta.1]: Removes incorrect deprecated markup 1a83eeecc0c [5.0.0.beta.2]: Removes unnecessary TODO 5da35b44d24 [5.0.0.beta.2]: Updates some missed Xcode settings 15a35b1fdd5 Updates CloudKit (#888) ae00288512f [Xcode 10 GM]: Updates README b43d66e49ba [Xcode 10 GM]: Bumps the version to 5.0.0 beta 2 64e4fde224a [Xcode 10 GM]: Sets mac OS deployment target. 2edc8f452a9 [Xcode 10 GM]: Forces Cocoapods 1.6.0 (beta 1) 6ace7ba2ad1 [Xcode 10 GM]: Updated pod install for TryProcedureKit 40c18a4c8c4 [Xcode 10GM]: Fixes test parallel options b2acdf71b69 [Xcode 10 GM]: Fixes issue post merge with Alert Style 56e3ff1bf27 [Xcode 10]: Updates project settings 151cc0631f8 [Xcode 10 GM]: Fixes Signpost Observer stuff e43ad5b5a39 Fixes after rebasing against latest development containing error refactor 02504a52d62 Fixes for changes related to UIViewController APIs 0897f2e0279 Adds ProcedureKitInstruments (#857) bb7ea65d546 Updates Swift version to 4.2 in podspecs 9b919d0a2bd Further fixes for iOS & tvOS 07d62c7ba1b Fixes for Mac tests b6b929f4393 Fixes for ProcedureKitClout for Xcode 10 & Swift 4.2
Beta 1 from 4.5.0
702562255eb Fixes mistake with Mobile podspec d44cff9208c Updates CHANGELOG for v5 4afa2daaa3c Sets the version to 5.0.0-beta.1 409a9fc58b3 Refactors AlertProcedure (#882) a15450c7673 Adds public access modifier to AutolayoutViews (#879) aae6711f376 Fixes a flaky test for BackgroundObserver (#877) 9b9b3ae9129 Refactors BlockProcedure (#875) b60bad656f2 Fixes bug where child would not be added to supplied view. (#874) 04e33cb83dc Fixes API mistakes with ViewControllerContainment stuff (#873) 0d9e3d7505c Fixes minor issues with new logging system (#870) ac3a9d7198f Makes block property public (#869) 84112b8f743 Fixes bug with UIBlockProcedure (#868) 76e6e4911e0 Moves TryProcedureKit integration tests into main repo (#867) c7bb0b01ae1 Refactors Logger (#861) eeba2978be9 Make new platform schemes used by CI test only schemes. (#864) c468a269b58 Renames API for Swift 3/4 naming conventions (#860) bdec58312b2 Sets the version to 5.0.0 🚀 (#859) dbd0cc7be51 Refactors Procedure to only finish with one optional error (#851) 5f84ee5718a Fixes bug where UIBlockProcedure can create a deadlock when added to the main queue (#858) af40b54a071 Adds UIView controller containment procedures (#841) 0b2841404f5 Rewrites CI pipeline (#850) ce9722d4fb7 [OPR-846]: Removes return objects as faults. (#849) 2879a248b0b Core Data fixes (#847) 44edd33471a Expose convenient initialiser for Retry (#845) 8bd0dbe75eb Fixes designated initializers in CoreData module (#844) ecdb5999930 Adds Core Data module (#843) e71548cc39a Adds UIBlockProcedure (#840) ad85784bbfc Fixes potential memory leak (#839) baf9bf5e37b Adds IgnoreErrorsProcedure (#838) 6e158353695 Swift 4.1 improvements (#837) 658cd6c78fa [OPR-825]: Tweaks the cancellation logic in ReverseGeocodeUserLocation (#835) 0f91e88dd44 Uses CocoaPods swift_version DSL (#822) 9579a68470e Adds BatchProcedure (#834) c1615f7c8ac Result Injection improvements (#833) 2fbbe3fd52e Updates for Swift 4.1 & Xcode 9.3 (#830) aed29a5d82a Fixes typo in ProcedureKit.podspec (#831) 57de0b87bef Adds full result injection support in RepeatProcedure etc (#828) e23387b8771 [OPR-826]: Updates Package.swift (#826) 435a0b26cf5 [OPR-814] Remove PATs from URLSessionTaskFactory to prevent Generics from leaking everywhere