{"id":25453580,"url":"https://github.com/xcessentials/functionalstate","last_synced_at":"2025-05-16T14:35:12.683Z","repository":{"id":56927782,"uuid":"77333881","full_name":"XCEssentials/FunctionalState","owner":"XCEssentials","description":"[DEPRECATED - use 'SwiftUI' instead] Turn any object into discrete system and describe its states declaratively.","archived":false,"fork":false,"pushed_at":"2018-04-24T22:27:09.000Z","size":394,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-18T10:01:45.643Z","etag":null,"topics":["cocoapod","finite-state-machine","swift","xcode"],"latest_commit_sha":null,"homepage":"https://xcessentials.github.io/FunctionalState/","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/XCEssentials.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":null,"security":null,"support":null}},"created_at":"2016-12-25T16:22:10.000Z","updated_at":"2019-07-20T14:06:05.000Z","dependencies_parsed_at":"2022-08-20T23:30:41.368Z","dependency_job_id":null,"html_url":"https://github.com/XCEssentials/FunctionalState","commit_stats":null,"previous_names":["xcessentials/state"],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XCEssentials%2FFunctionalState","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XCEssentials%2FFunctionalState/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XCEssentials%2FFunctionalState/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XCEssentials%2FFunctionalState/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/XCEssentials","download_url":"https://codeload.github.com/XCEssentials/FunctionalState/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239384679,"owners_count":19629509,"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":["cocoapod","finite-state-machine","swift","xcode"],"created_at":"2025-02-17T23:56:08.283Z","updated_at":"2025-02-17T23:56:08.895Z","avatar_url":"https://github.com/XCEssentials.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![GitHub tag](https://img.shields.io/github/tag/XCEssentials/FunctionalState.svg)](https://github.com/XCEssentials/FunctionalState/releases)\n[![CocoaPods](https://img.shields.io/cocoapods/v/XCEFunctionalState.svg)](https://cocoapods.org/?q=XCEFunctionalState)\n[![CocoaPods](https://img.shields.io/cocoapods/p/XCEFunctionalState.svg)](https://cocoapods.org/?q=XCEFunctionalState)\n[![license](https://img.shields.io/github/license/XCEssentials/FunctionalState.svg)](https://opensource.org/licenses/MIT)\n\n# Introduction\n\nTurn any object into discrete system and describe its states declaratively.\n\n\n\n# How to install\n\nThe recommended way is to install using [CocoaPods](https://cocoapods.org/?q=XCEFunctionalState):\n\n```ruby\npod 'XCEFunctionalState', '~\u003e 2.8'\n```\n\n\n\n# How it works\n\nThis library allows to turn any object into [discrete system](https://en.wikipedia.org/wiki/Discrete_system) by defining a number of distinct states and then applying these states instantly or via transition.\n\n\n\n# How to use\n\nA typical use case for this library is for re-configuring instances of `UIView` and its subclasses as your app state changes.\n\n\n\n## State\n\nEach state defines how it's being applied, as well as how it's being updated (when it's been requested to be applied while it's already current state), plus transitions for each of these operations (instant by default).\n\n\n\n## Stateful\n\nLet's say we have a class `SearchView` that represents a view with text field where user can enter their search keyword and button that starts a search process. It must conform to `Stateful` protocol to become discrete system.\n\n```swift\nimport XCEFunctionalState\n\nclass SearchView: Stateful\n{\n    let keyword = UITextField()\n    let start = UIButton()\n    \n    private(set)\n    lazy\n    var state: Dispatcher\u003cMyView\u003e = Dispatcher(for: self)\n}\n```\n\nTo describe a state for a given class, define a class level function (its name will be interpreted as the state name) inside this class that returns a `State` for this class.\n\nFor example, let's define `awaiting` state for our `SearchView` class in which both `keyword` text field and `start` button are enabled and available for user input. Note that we can define as many input parameters as we want for the function, and this gives us opportunity to pass any kind of values from the outside into the state configuration closure. See how in the example below we can pass default value for `keyword` field.\n\n```swift\nextension SearchView\n{\n    static\n    func awaiting(with keyword: String) -\u003e State\u003cSearchView\u003e\n    {\n        return state{\n\n            $0.keyword.text = keyword\n            $0.keyword.isEnabled = true\n            $0.start.isEnabled = true\n        }\n    }\n}\n```\n\nOnce user has entered search keyword and tapepd `start` button we may want to lock these controls while search is in progress. To do so, we may want to apply a state `locked` on the search view, which may be declared as follows:\n\n```swift\nextension SearchView\n{\n    static\n    func locked() -\u003e State\u003cSearchView\u003e\n    {\n        return state{\n\n            $0.keyword.isEnabled = false\n            $0.start.isEnabled = false\n        }\n    }\n}\n```\n\nLater in time, we can apply any of the states declared for the class to an instance of this class as follows:\n\n```swift\nlet transition: Transition\u003cSearchView\u003e = ... // define transition\nlet view = SearchView()\n\nview.state.apply{ $0.awaiting(with: \"something\") }\nview.state.apply{ $0.awaiting(with: \"another value\") } // no effect\nview.state.apply(via: transition, MyView.locked()){ /* completion*/ }\n//...\nview.state.apply{ $0.awaiting(with: \"after search\") }\n```\n\nBy default, all mutations are being applied instantly. When working with `UIView`-based classes, it's common to apply changes with animations, and `Transition` type gives full control over it.\n\n`Stateful` protocol also gives a chance to define transitions that should be used by default when we apply a state, but do not provide specific transition explicitly in the state definition.\n\n```swift\nextension SearchView\n{\n    static\n    var defaultOnSetTransition: Transition\u003cSearchView\u003e = {\n    \t\n    \t(view, mutations, completion) in\n\n        view.alpha = 0.0\n\n        //---\n\n        mutations() // this is closure from the state\n\n        //---\n\n        UIView.animate(\n        \twithDuration: 1.0,\n            animations: { v.alpha = 1.0 },\n            completion: completion\n        )\n    }\n    \n    static\n    var defaultOnUpdateTransition: Transition\u003cSearchView\u003e = {\n      \n      //...\n    }\n}\n```\n\n`defaultOnSetTransition` in listing above demonstrates transition that hides whole view, then applies mutations from the new state, and then fades in whole view with animation, making it visible again. Alternatively, we could put `mutations()` call inside `animations` closure of the `UIView.animate(…)` call to animate actual mutations during fade-in animation, if so desired.\n\n# Interoperability with Objective-C\n\nTo make the result code as concise and self explanatory as possible, as well as to maintaining compile time type safety, this library relies on advanced Swift language features like generics and closure shorthand argument names, so it is NOT intended to be compatible with Objective-C.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxcessentials%2Ffunctionalstate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxcessentials%2Ffunctionalstate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxcessentials%2Ffunctionalstate/lists"}