### Install Action Library using Carthage Source: https://github.com/rxswiftcommunity/action/blob/master/Readme.md Instructions for installing the Action library using Carthage. Add the specified GitHub repository and version to your Cartfile, then run 'carthage update'. Note version compatibility with RxSwift. ```sh github "RxSwiftCommunity/Action" ~> 5.0.0 ``` -------------------------------- ### Install Action Library using CocoaPods Source: https://github.com/rxswiftcommunity/action/blob/master/Readme.md Instructions for installing the Action library using CocoaPods. Add the specified line to your Podfile and run 'pod install'. ```ruby pod 'Action' ``` -------------------------------- ### Ruby: CocoaPods Dependency Management for Action Source: https://context7.com/rxswiftcommunity/action/llms.txt This Ruby snippet shows how to declare the `Action` library as a dependency in a `Podfile` for an iOS project. It specifies the platform version, enables framework usage, and lists `Action`, `RxSwift`, and `RxCocoa` as target dependencies. This setup ensures these libraries are correctly integrated into the Xcode project via CocoaPods. ```ruby # Podfile platform :ios, '9.0' use_frameworks! target 'YourApp' do pod 'Action' pod 'RxSwift', '~> 6.0' pod 'RxCocoa', '~> 6.0' end ``` -------------------------------- ### UIAlertAction Integration with RxSwift Action Source: https://context7.com/rxswiftcommunity/action/llms.txt Shows how to create UIAlertAction instances that are bound to an Action, enabling reactive handling of alert button taps. This example includes creating 'Delete' and 'Cancel' actions, with the 'Delete' action performing a simulated network request and handling success/error callbacks. Note the requirement to use UIAlertAction.Action() for binding. ```swift import UIKit import RxSwift import Action class AlertViewController: UIViewController { let disposeBag = DisposeBag() func showConfirmationAlert() { let alertController = UIAlertController( title: "Confirm Delete", message: "Are you sure you want to delete this item?", preferredStyle: .alert ) // Create OK action with work to perform var okAction = UIAlertAction.Action("Delete", style: .destructive) okAction.rx.action = CocoaAction { print("User confirmed deletion") return self.deleteItem() .do( onCompleted: { print("Item deleted successfully") self.dismiss(animated: true) }, onError: { error in print("Deletion failed: \(error)") self.showError(error) } ) .catch { _ in Observable.empty() } } alertController.addAction(okAction) // Create cancel action var cancelAction = UIAlertAction.Action("Cancel", style: .cancel) cancelAction.rx.action = CocoaAction { print("User cancelled") return Observable.empty() } alertController.addAction(cancelAction) // Observe enabled state changes let someCondition = Observable.just(true) okAction.rx.enabled.onNext(true) // Manually control enabled state if needed present(alertController, animated: true) } private func deleteItem() -> Observable { return Observable.empty() .delaySubscription(.seconds(1), scheduler: MainScheduler.instance) } private func showError(_ error: Error) { // Show error alert } } // Note: UIAlertAction must be created using UIAlertAction.Action() factory // Standard UIAlertAction(title:style:handler:) won't work with Action binding ``` -------------------------------- ### Bind Action to UIBarButtonItem with State Management (Swift) Source: https://context7.com/rxswiftcommunity/action/llms.txt Shows how to integrate RxCocoa Actions with UIBarButtonItems. Similar to UIButtons, Actions automatically manage the enabled state of the UIBarButtonItem and handle tap events. This example also demonstrates creating an action with an 'enabledIf' condition. ```swift import UIKit import RxSwift import Action class ViewController: UIViewController { let disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() // Create refresh action let refreshAction = CocoaAction { print("Refreshing data...") return self.loadDataFromNetwork() .do(onNext: { data in self.updateUI(with: data) }) .map { _ in () } // Convert to Void } // Bind to right bar button item navigationItem.rightBarButtonItem?.rx.action = refreshAction // Create save action with validation let hasUnsavedChanges = Observable.just(true) // In real app, track changes let saveAction = CocoaAction(enabledIf: hasUnsavedChanges) { print("Saving changes...") return self.saveChanges() } // Bind to left bar button item navigationItem.leftBarButtonItem?.rx.action = saveAction // Both buttons are automatically disabled while executing // Enable state is managed automatically } private func loadDataFromNetwork() -> Observable<[String]> { return Observable.just(["Item 1", "Item 2", "Item 3"]) .delaySubscription(.seconds(2), scheduler: MainScheduler.instance) } private func saveChanges() -> Observable { return Observable.empty() .delaySubscription(.seconds(1), scheduler: MainScheduler.instance) } private func updateUI(with data: [String]) { print("UI updated with: (data)") } } ``` -------------------------------- ### Action with Enabled State Control in Swift Source: https://context7.com/rxswiftcommunity/action/llms.txt Shows how to create an Action whose execution is controlled by an `enabledIf` observable, making it conditional on external factors like form validation. This example uses RxCocoa to bind UI text field inputs to validation logic. ```swift import RxSwift import RxCocoa import Action let emailTextField = UITextField() let passwordTextField = UITextField() // Validate email format func isValidEmail(_ email: String?) -> Bool { guard let email = email, !email.isEmpty else { return false } let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}" return NSPredicate(format: "SELF MATCHES %@", emailRegex).evaluate(with: email) } // Create validation observables let validEmail = emailTextField.rx.text .map { isValidEmail($0) } let validPassword = passwordTextField.rx.text .map { ($0?.count ?? 0) >= 8 } // Combine validation conditions let formIsValid = Observable.combineLatest(validEmail, validPassword) { $0 && $1 } // Create action that only executes when form is valid let submitAction = Action(enabledIf: formIsValid) { _ in let email = emailTextField.text ?? "" let password = passwordTextField.text ?? "" return URLSession.shared.rx.data(request: buildLoginRequest(email, password)) .map { try JSONDecoder().decode(LoginResponse.self, from: $0) } .catch { error in print("Login failed: \(error)") return Observable.error(error) } } // Action is only enabled when both email and password are valid submitAction.enabled .subscribe(onNext: { enabled in print("Submit action enabled: \(enabled)") }) .disposed(by: disposeBag) ``` -------------------------------- ### Basic Action Implementation and Observation in Swift Source: https://context7.com/rxswiftcommunity/action/llms.txt Demonstrates the creation of a basic Action in Swift that performs a network request to check email existence. It shows how to execute the action, subscribe to its results and errors, and observe its execution state using RxSwift. ```swift import RxSwift import Action // Basic action that checks if an email exists let action = Action { email in return URLSession.shared.rx.data(request: buildRequest(email)) .map { data in let response = try JSONDecoder().decode(EmailCheckResponse.self, from: data) return response.exists } } // Execute the action action.execute("user@example.com") .subscribe(onNext: { exists in print("Email exists: \(exists)") }, onError: { error in print("Error: \(error)") }) .disposed(by: disposeBag) // Observe execution state action.executing .subscribe(onNext: { isExecuting in print("Currently executing: \(isExecuting)") }) .disposed(by: disposeBag) // Observe all results action.elements .subscribe(onNext: { result in print("Result received: \(result)") }) .disposed(by: disposeBag) // Observe all errors action.errors .subscribe(onNext: { error in switch error { case .notEnabled: print("Action was disabled when execute() was called") case .underlyingError(let err): print("Work failed with error: \(err)") } }) .disposed(by: disposeBag) ``` -------------------------------- ### Using CocoaAction with RxSwift and RxCocoa Source: https://context7.com/rxswiftcommunity/action/llms.txt This Swift code demonstrates the basic usage of CocoaAction for binding UI events to asynchronous operations. It shows how to create an action, bind it to a button using RxCocoa's `rx.action` property, and define the work to be performed asynchronously. ```swift // Import in your Swift files import RxSwift import RxCocoa import Action class MyViewController: UIViewController { let disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() // Create and use actions let action = CocoaAction { return self.performWork() } // Bind to UI myButton.rx.action = action } private func performWork() -> Observable { return Observable.empty() .delaySubscription(.seconds(2), scheduler: MainScheduler.instance) } } ``` -------------------------------- ### Swift: Create and Execute an Action Source: https://github.com/rxswiftcommunity/action/blob/master/Readme.md Demonstrates how to create an Action with a work factory that returns an Observable. The Action takes an input type and an output type. The execute() method is used to trigger the action with specific input. ```swift action: Action = Action(workFactory: { input in return networkLibrary.checkEmailExists(input) }) ... action.execute("ash@ashfurrow.com") ``` -------------------------------- ### Swift Package Manager Dependency for Action Source: https://context7.com/rxswiftcommunity/action/llms.txt This snippet shows how to add the Action library as a dependency for your project using Swift Package Manager. It specifies the repository URL and version, and how to include it in your target's dependencies. ```swift // Swift Package Manager - Package.swift dependencies: [ .package(url: "https://github.com/RxSwiftCommunity/Action.git", from: "5.0.0") ], targets: [ .target( name: "YourTarget", dependencies: ["Action"]) ] ``` -------------------------------- ### CocoaAction for Simple UI Interactions in Swift Source: https://context7.com/rxswiftcommunity/action/llms.txt Illustrates the creation and execution of a CocoaAction, which is a typealias for Action suitable for simple UI interactions without input or output values. It shows two ways to define the action, including using delaySubscription. ```swift import RxSwift import Action // Create a simple action with a 2-second delay let buttonAction = CocoaAction { print("Button pressed, starting work...") return Observable.create { observer -> Disposable in DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { print("Work completed!") observer.onCompleted() } return Disposables.create() } } // Alternative using built-in operators let simpleAction = CocoaAction { return Observable.empty() .delaySubscription(.seconds(2), scheduler: MainScheduler.instance) } // Execute programmatically buttonAction.execute() .subscribe(onCompleted: { print("Action finished") }) .disposed(by: disposeBag) ``` -------------------------------- ### Create UIAlertAction with Action in Swift Source: https://github.com/rxswiftcommunity/action/blob/master/Readme.md Demonstrates how to create a UIAlertAction using the Action class in Swift. This snippet shows a basic initialization for a default style action with a title. ```swift let action = UIAlertAction.Action("Hi", style: .default) ``` -------------------------------- ### Swift: Complex Shared Action with Multiple Inputs Source: https://context7.com/rxswiftcommunity/action/llms.txt This Swift code defines a `DocumentViewController` that uses a single `Action` to handle various document operations like save, delete, and export. It binds multiple `UIButton` instances to this action, each with a specific input. The `Action` library manages the execution state, results, and errors centrally, simplifying UI updates and logic. Dependencies include `UIKit`, `RxSwift`, and `Action`. ```swift import UIKit import RxSwift import Action enum UserAction { case save case delete case export(format: String) } class DocumentViewController: UIViewController { let saveButton = UIButton() let deleteButton = UIButton() let exportPDFButton = UIButton() let exportCSVButton = UIButton() let activityIndicator = UIActivityIndicatorView() let statusLabel = UILabel() let disposeBag = DisposeBag() // Single action handling all document operations let documentAction = Action { action in switch action { case .save: return performSave() .map { "Document saved successfully" } .delaySubscription(.seconds(1), scheduler: MainScheduler.instance) case .delete: return performDelete() .map { "Document deleted successfully" } .delaySubscription(.seconds(2), scheduler: MainScheduler.instance) case .export(let format): return performExport(format: format) .map { "Document exported as \(format)" } .delaySubscription(.seconds(3), scheduler: MainScheduler.instance) } } override func viewDidLoad() { super.viewDidLoad() // Bind all buttons to the same action with different inputs saveButton.rx.bind(to: documentAction, input: .save) deleteButton.rx.bind(to: documentAction, input: .delete) exportPDFButton.rx.bind(to: documentAction, input: .export(format: "PDF")) exportCSVButton.rx.bind(to: documentAction, input: .export(format: "CSV")) // Centralized execution state management documentAction.executing .subscribe(onNext: { [weak self] executing in if executing { self?.activityIndicator.startAnimating() self?.statusLabel.text = "Working..." } else { self?.activityIndicator.stopAnimating() self?.statusLabel.text = "Ready" } }) .disposed(by: disposeBag) // Centralized result handling documentAction.elements .subscribe(onNext: { [weak self] message in self?.statusLabel.text = message self?.showSuccessToast(message) }) .disposed(by: disposeBag) // Centralized error handling documentAction.errors .subscribe(onNext: { [weak self] error in guard case .underlyingError(let underlyingError) = error else { return } self?.statusLabel.text = "Error occurred" self?.showErrorAlert(underlyingError) }) .disposed(by: disposeBag) // All buttons automatically share the same enabled state // Only one operation can run at a time // All buttons disabled while any operation executes } private func showSuccessToast(_ message: String) { print("Success: \(message)") } private func showErrorAlert(_ error: Error) { let alert = UIAlertController( title: "Error", message: error.localizedDescription, preferredStyle: .alert ) alert.addAction(UIAlertAction(title: "OK", style: .default)) present(alert, animated: true) } } // Helper functions private func performSave() -> Observable { return Observable.empty() } private func performDelete() -> Observable { return Observable.empty() } private func performExport(format: String) -> Observable { return Observable.empty() } ``` -------------------------------- ### Share One Action Across Multiple UIButtons with Dynamic Inputs (Swift) Source: https://context7.com/rxswiftcommunity/action/llms.txt Illustrates how to bind multiple UIButtons to a single RxCocoa Action, allowing each button to trigger the action with a different input value. The 'bind(to:input:)' method is used for static inputs, while a closure can be used for dynamic input generation based on the control's state. ```swift import UIKit import RxSwift import Action let button1 = UIButton() let button2 = UIButton() let button3 = UIButton() // Action that processes different payment methods let processPaymentAction = Action { paymentMethod in print("Processing payment with: (paymentMethod)") return Observable.create { observer -> Disposable in // Simulate payment processing DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { observer.onNext(PaymentResult(method: paymentMethod, success: true)) observer.onCompleted() } return Disposables.create() } } // Bind each button to the same action with different inputs button1.rx.bind(to: processPaymentAction, input: "Credit Card") button2.rx.bind(to: processPaymentAction, input: "PayPal") button3.rx.bind(to: processPaymentAction, input: "Apple Pay") // All buttons share the same enabled state // Only one can execute at a time // All are disabled while any one executes // Observe results from any button processPaymentAction.elements .subscribe(onNext: { result in print("\(result.method) payment succeeded: \(result.success)") }) .disposed(by: disposeBag) // Alternative: use closure for dynamic input let dynamicButton = UIButton() dynamicButton.rx.bind(to: processPaymentAction) { button -> String in return button.titleLabel?.text ?? "Unknown" } ``` -------------------------------- ### Swift: Action with Enabled Condition Source: https://github.com/rxswiftcommunity/action/blob/master/Readme.md Shows how to initialize an Action with an 'enabledIf' parameter. This condition, typically a signal, controls whether the action can be executed. It combines with the action's internal 'executing' state to determine the overall enabled status. ```swift let validEmailAddress = emailTextField.rx.text.map(isValidEmail) action: Action = Action(enabledIf: validEmailAddress, workFactory: { input in return networkLibrary.checkEmailExists(input) }) ``` -------------------------------- ### Bind Action to UIButton with State Management (Swift) Source: https://context7.com/rxswiftcommunity/action/llms.txt Demonstrates how to bind an RxCocoa Action directly to a UIButton. The action automatically manages the button's enabled state and handles tap events. The 'executing' observable can be used to update UI elements during the action's execution. ```swift import UIKit import RxSwift import RxCocoa import Action let submitButton = UIButton() let disposeBag = DisposeBag() // Create an action let submitAction = CocoaAction { print("Submitting form...") return Observable.empty() .delaySubscription(.seconds(3), scheduler: MainScheduler.instance) .do(onCompleted: { print("Form submitted!") }) } // Bind action to button - one line! submitButton.rx.action = submitAction // Button is now: // - Automatically disabled while action executes // - Taps trigger the action // - Enabled state bound to action.enabled // Observe execution state for UI updates submitAction.executing .subscribe(onNext: { executing in if executing { submitButton.setTitle("Submitting...", for: .normal) } else { submitButton.setTitle("Submit", for: .normal) } }) .disposed(by: disposeBag) ``` -------------------------------- ### Observe Action State, Results, and Errors in Swift Source: https://context7.com/rxswiftcommunity/action/llms.txt Monitor the execution state (executing/enabled), successful results (elements), and all errors (including .notEnabled and underlying errors) emitted by an RxAction. This allows for comprehensive UI updates and error handling during asynchronous operations. ```swift import RxSwift import Action let disposeBag = DisposeBag() // Create an action that may fail let networkAction = Action { urlString in guard let url = URL(string: urlString) else { return Observable.error(NSError(domain: "Invalid URL", code: -1)) } return URLSession.shared.rx.data(request: URLRequest(url: url)) } // Observe execution state (true/false) networkAction.executing .distinctUntilChanged() .subscribe(onNext: { executing in if executing { print("🔄 Action started executing") showLoadingSpinner() } else { print("✅ Action finished executing") hideLoadingSpinner() } }) .disposed(by: disposeBag) // Observe successful results networkAction.elements .subscribe(onNext: { data in print("📦 Received data: (data.count) bytes") processData(data) }) .disposed(by: disposeBag) // Observe ALL errors (including .notEnabled) networkAction.errors .subscribe(onNext: { error in switch error { case .notEnabled: print("⚠️ Action was not enabled when executed") case .underlyingError(let underlyingError): print("❌ Error occurred: (underlyingError)") showErrorAlert(underlyingError) } }) .disposed(by: disposeBag) // Observe only underlying errors (filter out .notEnabled) networkAction.underlyingError .subscribe(onNext: { error in print("❌ Underlying error: (error)") }) .disposed(by: disposeBag) // Observe enabled state networkAction.enabled .subscribe(onNext: { enabled in print("🎛 Action enabled: (enabled)") }) .disposed(by: disposeBag) // Execute the action networkAction.execute("https://api.example.com/data") .subscribe( onNext: { data in print("Individual execution result: (data)") }, onError: { error in print("Individual execution error: (error)") }, onCompleted: { print("Individual execution completed") } ) .disposed(by: disposeBag) ``` -------------------------------- ### Track Completion of Actions Without Values in Swift Source: https://context7.com/rxswiftcommunity/action/llms.txt Utilize CompletableAction (Action) to manage operations that complete without emitting any output values. This is ideal for tasks like saving data or logging out, where only the success or failure of the operation matters. ```swift import RxSwift import Action let disposeBag = DisposeBag() // Create a completable action (no output values) let saveAction: CompletableAction = Action { filename in print("Saving file: (filename)") return Observable.create { observer in // Simulate file save operation DispatchQueue.global().asyncAfter(deadline: .now() + 1.0) { // Perform save operation print("File saved: (filename)") // Complete without emitting values observer.onCompleted() } return Disposables.create() } } // Observe completions specifically (only successful completions) saveAction.completions .subscribe(onNext: { print("✅ Save operation completed successfully!") showSuccessMessage() }) .disposed(by: disposeBag) // Observe errors separately saveAction.errors .subscribe(onNext: { error in print("❌ Save operation failed: (error)") showErrorMessage() }) .disposed(by: disposeBag) // Execute the action saveAction.execute("document.txt") .subscribe( onCompleted: { print("Individual save completed") }, onError: { error in print("Individual save failed: (error)") } ) .disposed(by: disposeBag) // Another example: CompletableAction for logout let logoutAction: CompletableAction = CocoaAction { return Completable.create { completable in // Clear user session UserSession.shared.clear() // Navigate to login screen DispatchQueue.main.async { navigateToLogin() } completable(.completed) return Disposables.create() }.asObservable() } logoutAction.completions .subscribe(onNext: { print("User logged out successfully") }) .disposed(by: disposeBag) ``` -------------------------------- ### Swift: Multiple Buttons with Single Action Source: https://github.com/rxswiftcommunity/action/blob/master/Readme.md Demonstrates how to bind multiple UIButtons to a single Action, each providing different input to the action's work factory. The rx.bindTo operator is used with a closure to map the button tap event to the specific input required by the action. ```swift let button1 = UIButton() let button2 = UIButton() let action = Action { input in print(input) return .just(input) } button1.rx.bindTo(action) { _ in return "Hello"} button2.rx.bindTo(action) { _ in return "Goodbye"} ``` -------------------------------- ### Swift: Bind UIButton to Action Source: https://github.com/rxswiftcommunity/action/blob/master/Readme.md Illustrates the integration of a UIButton with an Action using the rx.action extension. This automatically manages the button's enabled state, binding it to the action's enabled property, and prevents multiple executions while the action is in progress. ```swift button.rx.action = action ``` -------------------------------- ### UIRefreshControl Integration with RxSwift Action Source: https://context7.com/rxswiftcommunity/action/llms.txt Demonstrates how to bind a CocoaAction to a UIRefreshControl for pull-to-refresh functionality. The action automatically manages the refresh indicator's spinning state based on the execution status. It handles network requests and updates the UI, with error handling. ```swift import UIKit import RxSwift import RxCocoa import Action class TableViewController: UIViewController { let scrollView = UIScrollView() let disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() let refreshControl = UIRefreshControl() scrollView.addSubview(refreshControl) // Create refresh action let refreshAction = CocoaAction { print("Pull to refresh triggered") return URLSession.shared.rx.data(request: buildAPIRequest()) .map { data -> [Item] in return try JSONDecoder().decode([Item].self, from: data) } .do( onNext: { items in print("Loaded \(items.count) items") self.updateTableView(with: items) }, onCompleted: { print("Refresh completed!") }, onError: { error in print("Refresh failed: \(error)") self.showErrorAlert(error) } ) .map { _ in () } // Convert to Void for CocoaAction .catch { _ in Observable.empty() } // Handle errors gracefully } // Bind action to refresh control // Spinning state automatically managed by action.executing refreshControl.rx.action = refreshAction // Optional: observe execution state for additional UI updates refreshAction.executing .subscribe(onNext: { executing in UIApplication.shared.isNetworkActivityIndicatorVisible = executing }) .disposed(by: disposeBag) } private func updateTableView(with items: [Item]) { // Update your table view } private func showErrorAlert(_ error: Error) { // Show error to user } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.