{"id":20935428,"url":"https://github.com/ww-tech/lasso","last_synced_at":"2025-04-05T06:06:56.464Z","repository":{"id":42045688,"uuid":"238792017","full_name":"ww-tech/lasso","owner":"ww-tech","description":"iOS architectural pattern and framework","archived":false,"fork":false,"pushed_at":"2025-01-13T22:00:20.000Z","size":1459,"stargazers_count":92,"open_issues_count":3,"forks_count":19,"subscribers_count":4,"default_branch":"develop","last_synced_at":"2025-03-29T05:06:40.439Z","etag":null,"topics":["architecture","ios","swift","unidirectional-data-flow"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ww-tech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"publiccode":null,"codemeta":null}},"created_at":"2020-02-06T21:51:25.000Z","updated_at":"2025-01-13T21:25:20.000Z","dependencies_parsed_at":"2024-06-07T12:46:45.647Z","dependency_job_id":"8281b052-b384-4d82-b646-7732b9cd0ba3","html_url":"https://github.com/ww-tech/lasso","commit_stats":{"total_commits":138,"total_committers":13,"mean_commits":"10.615384615384615","dds":0.6304347826086957,"last_synced_commit":"752a6134a08909cc8f7a3d343312defeb9d38239"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ww-tech%2Flasso","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ww-tech%2Flasso/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ww-tech%2Flasso/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ww-tech%2Flasso/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ww-tech","download_url":"https://codeload.github.com/ww-tech/lasso/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247294536,"owners_count":20915340,"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":["architecture","ios","swift","unidirectional-data-flow"],"created_at":"2024-11-18T22:14:55.836Z","updated_at":"2025-04-05T06:06:56.447Z","avatar_url":"https://github.com/ww-tech.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\u003cimg src=\"docs/images/Lasso_Logo.svg\" width=\"75%\" alt=\"Lasso logo\" /\u003e\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Swift-4.2%20--%205.10-b63bdb.svg?style=flat\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/iOS-13.0%20--%2017.x-208eff.svg?style=flat\" /\u003e\n\u003c/p\u003e\n\nLasso is an iOS application architecture for building discrete, composable and testable components both big and small - from single one-off screens, through complex flows, to high-level application structures.\n\n\n\n## Why Lasso?\n\nWithout a set of structural principles, it's very easy for an application's code base to become hard to both reason about, and maintain.  In particular, these problems will eventually arise:\n\n- tight coupling of components makes it hard to change/test things\n- business logic living in strange places makes it hard to modify/reuse/debug/test existing code\n- view presentation choices made in inappropriate places makes it hard to refactor/reorganize/test flows\n- inconsistent organization across team makes it hard to cross-contribute\n\n\n\n## The Lasso way\n\nLasso encourages a strong separation of concerns by clearly defining discrete, single-responsibility components where specific types of code should live, and a clear, flexible way for these components to communicate.  Larger units of behavior are easily composed, and re-composed.\n\n### Screens\n\nWe generally think of a screen as a single page/view in an app - e.g., a login view, a contacts list view, an audio settings view, etc.\n\nIn Lasso, a `Screen` is the collection of types used to implement a single view:\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"docs/images/screen.svg\" width=\"75%\" alt=\"Diagram of a Screen and its constituent parts\" /\u003e\u003c/p\u003e\n\nThe `View` (i.e., a `UIViewController`) is responsible for:\n\n- accurately rendering the current `State` (i.e., the content) of the screen\n- forwarding user interactions to the `Store` (i.e., the decision maker)\n- responding to state changes to keep the presentation up to date\n\nLasso views tend to be small, with practically zero logic in them.\n\nA **unidirectional data flow** is used to ensure consistency: a `View` never re-renders anything in direct response to a user action.  `Views` send `Actions` to the `Store`, which updates the `State`, which come back to the `View` as `State` change notifications.\n\nThe `Store` is where a screen's decisions are made, and is the source of truth for the screen's `State`.  A `Store` is responsible for:\n\n- all business logic for the screen\n- responding to `Actions` (i.e. events sent from the `View`)\n- updates to the screen's `State`\n\nA `Store` can also generate an `Output` when an event occurs that is more appropriately handled elsewhere.  E.g., a login screen might generate a \"user did login\" output as a signal to a higher-level system to move to a logged-in portion of an app; or a contact list screen might generate a \"did select contact\" output as a signal to a higher-level flow to either present or push a contact detail screen.\n\n### Flows\n\nA `Flow` represents a feature - or area - of an app, and is commonly composed of a collection of `Screens`.  For example, a \"new user\" flow might be composed of a series of one-time informational screens followed by a single \"let's get started\" screen.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"docs/images/flow.svg\" width=\"80%\" min-width=\"300\" alt=\"Diagram of a Flow\" /\u003e\u003c/p\u003e\n\nA `Flow` is instantiated and started within an appropriate context of a view hierarchy (e.g., a \"sign up\" flow might be presented on a menu screen, or a \"welcome\" flow might be pushed onto a navigation stack).  The `Flow` starts by creating its initial `Screen`, and listens for `Output` signals.  As `Outputs` arrive, the `Flow` decides what to do with them - it can create and place another `Screen` into the view hierarchy, emit its own `Output` (when an event occurs that is more appropriately handled elsewhere), or whatever is appropriate for the `Flow`.\n\nSince `Screens` and `Flows` are encapsulated modules with discrete entry and exit points, it's quite easy and common for a `Flow` to manage both `Screens` _and_ `Flows`.  In this way, it becomes possible to define your application as a hierarchy of components, reducing complexity from the top level down.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"docs/images/flow-flow-screen.svg\" alt=\"Diagram of a Flow within another Flow\" /\u003e\u003c/p\u003e\n\n## Example App\n\nTo run the example project\n\n1. Clone the Lasso repo\n2. Run `pod install` from the `Example` directory\n3. Open up `Lasso.xcworkspace`\n\n\n\n## Learn more\n\n- [Lasso: Introducing a new architectural framework for iOS](docs/Lasso-Introduction-part1.md) - article that introduces Lasso, with a concrete example of creating a `Screen`\n- [Lasso: An introduction to Flows](docs/Lasso-FlowsIntro.md) - article that shows how to orchestrate a number of `Screens` with a `Flow`\n- [Lasso coding style guide](docs/style-guide.md) - tips for writing Swifty Lasso\n- [Notes about declaring types](docs/declaring-types-notes.md) - more details and best practices about declaring Lasso types\n- [Memory management](docs/memory-management.md) - information about memory management in Lasso, and tips to avoid strong reference cycles:\n\n\n## Requirements\n\nLasso supports **iOS 13 and up**, and can be compiled with **Swift 4.2 and up**.\n\nNote: Lasso v.1.3.0 has added support for SwiftUI, and has a minimum deployment target of iOS 13.0.  If you need support for earlier versions of iOS, please use v1.2.1.\n\n\n\n## Installation\n\n### Cocoapods\n\nThe core Lasso framework is added to the primary target in your Podfile:\n\n```ruby\nPod 'Lasso'\n```\n\nAlso add `LassoTestUtilities` to your test target(s):\n\n```ruby\nPod 'LassoTestUtilities'\n```\n\n\n\n### Swift Package Manager\n\nThe Lasso package URL is:\n\n```\n`https://github.com/ww-tech/lasso.git`\n```\n\nFor sample usage, see: [Swift Package Manager Sample](Example/SwiftPM/ReadMe.md).\n\n\n\n### Tuist\n\nTo add `Lasso` as a *tuist* `TargetDependency`:\n* clone this repo to the preferred location\n* create a `.project` dependency\n* add the dependency to your target dependency\n\n```swift\nlet lasso: TargetDependency = .project(target: \"Lasso\", path: \"../../path-to-lasso-repo-clone/\")\n\nlet demo = Target(\n    name: \"Demo\",\n    platform: .iOS,\n    product: .framework,\n    bundleId: \"com.example.Demo\",\n    dependencies: [ lasso ]\n)\n```\n\nAlso add `LassoTestUtilities` to your test target(s):\n\n```swift\nlet lassoTestUtilities: TargetDependency = .project(target: \"LassoTestUtilities\", path: \"../../path-to-lasso-repo-clone/\")\n\nlet demoTests = Target(\n    name: \"DemoTests\",\n    platform: .iOS,\n    product: .unitTests,\n    bundleId: \"com.example.DemoTests\",\n    dependencies: [ LassoTestUtilities ]\n)\n```\n\n\n## Contributing\n\nWe love contributions!\n\nIf you have a feature in mind, and/or have found a bug, the best thing to do is:\n\n1. Search the issues to see if someone has already brought it up!\n2. Create a new issue that explains in detail the improvements you'd like to see.\n3. If you have a code change in mind, that's awesome!\n   1. Fork the Lasso repo\n   2. Create a branch for your feature change\n   3. Open a PR!\n\n\n\n## Authors\n\n[Steven Grosmark](https://github.com/g-mark), [Trevor Beasty](https://github.com/trevor-beasty), Yuichi Kuroda, and the WW iOS Team.\n\n\n\n## License\n\nLasso is licensed under the [Apache-2.0 Open Source license](http://choosealicense.com/licenses/apache-2.0/).\n\nYou are free to do with it as you please.  We _do_ welcome attribution, and would love to hear from you if you are using it in a project!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fww-tech%2Flasso","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fww-tech%2Flasso","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fww-tech%2Flasso/lists"}