{"id":13905793,"url":"https://github.com/iZettle/Flow","last_synced_at":"2025-07-18T03:31:37.445Z","repository":{"id":31905098,"uuid":"113295091","full_name":"iZettle/Flow","owner":"iZettle","description":"Flow is a Swift library for working with asynchronous flows and life cycles","archived":false,"fork":false,"pushed_at":"2024-03-25T07:27:34.000Z","size":548,"stargazers_count":231,"open_issues_count":4,"forks_count":12,"subscribers_count":56,"default_branch":"master","last_synced_at":"2024-03-26T13:56:37.077Z","etag":null,"topics":["asynchronous","flow","functional","ios","lifecycle","manual-deployment","reactive","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iZettle.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2017-12-06T09:20:37.000Z","updated_at":"2024-03-31T01:37:01.751Z","dependencies_parsed_at":"2024-03-31T01:36:57.858Z","dependency_job_id":"4d83aa5a-f2ef-414b-b259-5e6ab69d3ada","html_url":"https://github.com/iZettle/Flow","commit_stats":{"total_commits":188,"total_committers":22,"mean_commits":8.545454545454545,"dds":0.7659574468085106,"last_synced_commit":"7ca28339de290e1b74de5cbf0def562810c07154"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iZettle%2FFlow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iZettle%2FFlow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iZettle%2FFlow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iZettle%2FFlow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iZettle","download_url":"https://codeload.github.com/iZettle/Flow/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226336691,"owners_count":17608877,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asynchronous","flow","functional","ios","lifecycle","manual-deployment","reactive","swift"],"created_at":"2024-08-06T23:01:23.811Z","updated_at":"2024-11-25T13:31:56.528Z","avatar_url":"https://github.com/iZettle.png","language":"Swift","readme":"\u003cimg src=\"https://github.com/iZettle/Flow/blob/master/flow-logo.png?raw=true\" height=\"140px\" /\u003e\n\n[![Platforms](https://img.shields.io/badge/platform-%20iOS%20|%20macOS%20|%20tvOS%20|%20linux-gray.svg)](https://img.shields.io/badge/platform-%20iOS%20|%20macOS%20|%20tvOS%20|%20linux-gray.svg)\n[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![Swift Package Manager Compatible](https://img.shields.io/badge/SwiftPM-Compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager)\n![Xcode version](https://img.shields.io/badge/Xcode-16.0.0-green)\n\nModern applications often contain complex asynchronous flows and life cycles. Flow is a Swift library aiming to simplify building these by solving three main problems:\n\n- **[Lifetime management](Documentation/LifetimeManagement.md)**: Managing long-living resources.\n- **[Event handling](Documentation/Signals.md)**: Signaling and observing events over time.\n- **[Asynchronous operations](Documentation/Futures.md)**: Handle results that might not yet be available.\n- **[Comparison to RxSwift](Documentation/RxSwiftComparison.md)**: Why you might choose Flow over something like RxSwift.\n\nFlow was carefully designed to be:\n\n- **Easy to use**: APIs are carefully designed for readability and ease of use.\n- **Pragmatic**: Evolved and designed to solve real problems.\n- **Composable**: Types compose nicely making building complex flows easy.\n- **Performant**: Flow has been highly tuned for performance.\n- **Concurrent**: Flow is thread safe and uses a scheduler model that is easy to reason about.\n- **Extensible**: Flow was designed to be extensible.\n- **Strongly typed**: Flow makes use of Swift strong typing to better express intention.\n- **Correct**: Backed by hundreds of unit tests and field tested for years.\n\n## Example usage\n\nIn Flow the `Disposable` protocol is used for lifetime management:\n\n```swift\nextension UIView {\n  func showSpinnerOverlay() -\u003e Disposable {\n    let spinner = ...\n    addSubview(spinner)\n    return Disposer {\n      spinner.removeFromSuperview()\n    }\n  }\n}\n\nlet disposable = view.showSpinnerOverlay()\n\ndisposable.dispose() // Remove spinner\n```\n\n`Disposable` resources can be collected in a common `DisposeBag`:\n```swift\nlet bag = DisposeBag() // Collects resources to be disposed together\n\nbag += showSpinnerOverlay()\nbag += showLoadingText()\n\nbag.dispose() // Will dispose all held resources\n```\n\nAnd the `Signal\u003cT\u003e` type is used for event handling. Signals are provided by standard UI components:\n\n```swift\nlet bag = DisposeBag()\n\n// UIButton provides a Signal\u003c()\u003e\nlet loginButton = UIButton(...)\n\nbag += loginButton.onValue {\n  // Log in user when tapped\n}\n\n// UITextField provides a ReadSignal\u003cString\u003e\nlet emailField = UITextField(...)\nlet passwordField = UITextField(...)\n\n// Combine and transform signals\nlet enableLogin: ReadSignal\u003cBool\u003e = combineLatest(emailField, passwordField)\n  .map { email, password in\n    email.isValidEmail \u0026\u0026 password.isValidPassword\n  }\n\n// Use bindings and key-paths to update your UI on changes\nbag += enableLogin.bindTo(loginButton, \\.isEnabled)\n```\n\nAnd finally the `Future\u003cT\u003e` type handles asynchronous operations:\n\n```swift\nfunc login(email: String, password: String) -\u003e Future\u003cUser\u003e {\n  let request = URLRequest(...)\n  return URLSession.shared.data(for: request).map { data in\n    User(data: data)\n  }\n}\n\nlogin(...).onValue { user in\n  // Handle successful login\n}.onError { error in\n  // Handle failed login\n}\n```\n\nThese three types come with many extensions that allow us to compose complex UI flows:\n\n```swift\nclass LoginController: UIViewController {\n  let emailField: UITextField\n  let passwordField: UITextField\n  let loginButton: UIButton\n  let cancelButton: UIBarButtonItem\n\n  var enableLogin: ReadSignal\u003cBool\u003e { /* Introduced above */ }\n  func login(email: String, password: String) -\u003e Future\u003cUser\u003e { /* Introduced above */ }\n  func showSpinnerOverlay() -\u003e Disposable { /* Introduced above */ }\n\n  // Returns future that completes with true if user chose to retry\n  func showRetryAlert(for error: Error) -\u003e Future\u003cBool\u003e { ... }\n\n  // Will setup UI observers and return a future completing after a successful login\n  func runLogin() -\u003e Future\u003cUser\u003e {\n    return Future { completion in // Complete the future by calling this with your value\n      let bag = DisposeBag() // Collect resources to keep alive while executing\n\n      // Make sure to signal at once to set up initial enabled state\n      bag += enableLogin.atOnce().bindTo(loginButton, \\.isEnabled)  \n\n      // If button is tapped, initiate potentially long running login request using input\n      bag += combineLatest(emailField, passwordField)\n        .drivenBy(loginButton)\n        .onValue { email, password in\n          login(email: email, password: password)\n            .performWhile {\n              // Show spinner during login request\n              showSpinnerOverlay()\n            }.onErrorRepeat { error in\n              // If login fails with an error show an alert...\n              // ...and retry the login request if the user chooses to\n              showRetryAlert(for: error)\n            }.onValue { user in\n              // If login is successful, complete runLogin() with the user\n              completion(.success(user))\n        }\n      }\n\n      // If cancel is tapped, complete runLogin() with an error\n      bag += cancelButton.onValue {\n        completion(.failure(LoginError.dismissed))\n      }\n\n      return bag // Return a disposable to dispose once the future completes\n    }\n  }\n}\n```\n\n## Requirements\n\n- Xcode `9.3+`\n- Swift 4.1\n- Platforms:\n  * iOS `9.0+`\n  * macOS `10.11+`\n  * tvOS `9.0+`\n  * watchOS `2.0+`\n  * Linux\n\n## Installation\n\n#### [Carthage](https://github.com/Carthage/Carthage)\n\n```shell\ngithub \"iZettle/Flow\" \u003e= 1.0\n```\n\n#### [Cocoa Pods](https://github.com/CocoaPods/CocoaPods)\n\n```ruby\nplatform :ios, '9.0'\nuse_frameworks!\n\ntarget 'Your App Target' do\n  pod 'FlowFramework', '~\u003e 1.0'\nend\n```\n\n#### [Swift Package Manager](https://github.com/apple/swift-package-manager)\n\n```swift\nimport PackageDescription\n\nlet package = Package(\n  name: \"Your Package Name\",\n  dependencies: [\n      .Package(url: \"https://github.com/iZettle/Flow.git\",\n               majorVersion: 1)\n  ]\n)\n```\n\n## Introductions\n\nIntroductions to the main areas of Flow can be found at:\n\n- [Lifetime management](Documentation/LifetimeManagement.md)\n- [Event handling](Documentation/Signals.md)\n- [Asynchronous operations](Documentation/Futures.md)\n\nTo learn even more about available functionality you are encouraged to explore the source files that are extensively documented. Code-completion should also help you to discover many of the transformations available on signals and futures.\n\n## Learn more\n\nTo learn more about the design behind Flow's APIs we recommend reading the following articles. They go more into depth about why Flow's types and APIs look and behave the way they do and give you some insights into how they are implemented:\n\n- [Introducing Flow](https://medium.com/izettle-engineering/introducing-flow-42de51988aea)\n- [Deriving Signals](https://medium.com/izettle-engineering/deriving-signal-2adb8687e9bf)\n- [Deriving Future](https://medium.com/izettle-engineering/deriving-future-607aea9abdee)\n- [Expanding on Signals](https://medium.com/izettle-engineering/expanding-on-signals-ad25daee4d64)\n\nAnd to learn how other frameworks can be built using Flow:\n\n- [Introducing Presentation](https://medium.com/izettle-engineering/introducing-presentation-presenting-ui-made-easy-134d3fbe9311)\n- [Introducing Form](https://medium.com/izettle-engineering/introducing-form-layout-styling-and-event-handling-b668d09bb4e6)\n\n## Frameworks built on Flow\n\nIf your target is iOS, we highly recommend that you also checkout these frameworks that are built on top of Flow:\n\n- **[Presentation](https://github.com/izettle/presentation)** - Formalizing presentations from model to result\n- **[Form](https://github.com/izettle/form)** - Layout, styling, and event handling\n\n## Field tested\n\nFlow was developed, evolved and field-tested over the course of several years, and is pervasively used in [iZettle](https://izettle.com)'s highly acclaimed point of sales app.\n\n## Collaborate\n\nYou can collaborate with us on our Slack workspace. Ask questions, share ideas or maybe just participate in ongoing discussions. To get an invitation, write to us at [iz-apps-platform-ios@paypal.com](mailto:iz-apps-platform-ios@paypal.com)\n","funding_links":[],"categories":["HarmonyOS"],"sub_categories":["Windows Manager"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FiZettle%2FFlow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FiZettle%2FFlow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FiZettle%2FFlow/lists"}