DMAction is a Swift SDK that provides a framework for defining and handling actions with retry and fallback mechanisms. It offers a flexible way to manage asynchronous actions and handle errors gracefully.
- Define actions with retry and fallback mechanisms
- Handle asynchronous actions with completion handlers
- Protocol-based design for easy integration
- Simple and intuitive API
To integrate DMAction into your Xcode project using CocoaPods, specify it in your Podfile:
pod 'DMAction'Then, run the following command:
pod installTo integrate DMAction into your Xcode project using Swift Package Manager, add it to the dependencies array in your Package.swift file:
dependencies: [
.package(url: "https://github.com/nikolay-dementiev/DMAction.git", branch: "main")
]But the main power was explained in the section below A More Advanced Example:
let buttonAction = DMButtonAction {
print("Button action performed")
}
buttonAction { _ in
...
}let buttonTest = UIButton(type: .system)
// If the result is completely uninteresting (muted)
buttonTest.addTarget(self,// `self` here is some UIKit object where the action's function exists
action: #selector(buttonTestActionWithMutedResult),
for: .touchUpInside)
// OR:
// if you need to process the result
buttonTest.addTarget(self,// `self` here is some UIKit object where the action's function exists
action: #selector(buttonTestActionWithHandledResult),
for: .touchUpInside)
@objc
func buttonTestActionWithMutedResult() {
let primaryButtonAction = DMButtonAction(makeActionWithFailureResult)
let fallbackButtonAction = DMButtonAction(makeActionWithSuccessResult)
primaryButtonAction
.retry(2)
.fallbackTo(fallbackButtonAction)
.simpleAction()
}
@objc
func buttonTestActionWithHandledResult() {
let primaryButtonAction = DMButtonAction(makeActionWithFailureResult)
let fallbackButtonAction = DMButtonAction(makeActionWithSuccessResult)
primaryButtonAction
.retry(2)
.fallbackTo(fallbackButtonAction)() { result in
// do something with result
}
}
func makeActionWithFailureResult(completion: @escaping (DMButtonAction.ResultType) -> Void) {
// ... do something
completion(.failure(NSError(domain: "TestDomain",
code: 404,
userInfo: nil)))
}
func makeActionWithSuccessResult(completion: @escaping (DMButtonAction.ResultType) -> Void) {
// ... do something
let yourResultVaue: Copyable = "\(#function) succeded!"
completion(.success(yourResultVaue))
}...
var body: some View {
// If the result is completely uninteresting (muted)
Button("Test button with muted result", action: buttonTestActionWithMutedResult)
// if you need to process the result
Button("Test button with handled result", action: buttonTestActionWithHandledResult)
}
...
func buttonTestActionWithMutedResult() {
let primaryButtonAction = DMButtonAction(makeActionWithFailureResult)
let fallbackButtonAction = DMButtonAction(makeActionWithSuccessResult)
primaryButtonAction
.retry(2)
.fallbackTo(fallbackButtonAction)
.simpleAction()
}
func buttonTestActionWithHandledResult() {
let primaryButtonAction = DMButtonAction(makeActionWithFailureResult)
let fallbackButtonAction = DMButtonAction(makeActionWithSuccessResult)
primaryButtonAction
.retry(2)
.fallbackTo(fallbackButtonAction)() { result in
// do something with result
}
}
func makeActionWithFailureResult(completion: @escaping (DMButtonAction.ResultType) -> Void) {
// ... do something
completion(.failure(NSError(domain: "TestDomain",
code: 404,
userInfo: nil)))
}
func makeActionWithSuccessResult(completion: @escaping (DMButtonAction.ResultType) -> Void) {
// ... do something
let yourResultVaue: Copyable = "\(#function) succeded!"
completion(.success(yourResultVaue))
}- An example with two different actions (primaryButtonAction and fallbackButtonAction) combined
into a single execution chain using
.retry(1):1represents the maximum number of retry attempts forprimaryButtonAction. It will be executed until either it succeeds or the retry limit is reached.- If
primaryButtonActionfails after the maximum attempts,fallbackButtonActionwill be triggered viafallbackTo(...).
// Primary action
let primaryButtonAction = DMButtonAction { completion in
completion(.failure(NSError(domain: "TestError", code: 1, userInfo: nil)))
}
// Fallback action
let fallbackButtonAction = DMButtonAction { completion in
completion(.success(MockCopyable(value: "Fallback Success")))
}
// Create execution chain
let actionWithFallback = primaryButtonAction
.retry(1) //The number of retry action before fallback
.fallbackTo(fallbackButtonAction)
var resultOfAction: DMAction.ResultType?
actionWithFallback { result in
// `unwrapValue()`: get rid of the wrapper - return the original result value that
// was passed via DMButtonAction' completion closure
print("the result value: \(result.unwrapValue())")
// `attemptCount`: contains UInt number of action's attemps
print("attemptCount: \(result.attemptCount)")
resultOfAction = result
}
if case .success(let copyableValue) = resultOfAction {
...
} else {
...
}This project is licensed under the MIT License - see the LICENSE file for details.
