{"id":14985961,"url":"https://github.com/onmyway133/easyclosure","last_synced_at":"2025-08-20T14:32:32.221Z","repository":{"id":56909686,"uuid":"187398766","full_name":"onmyway133/EasyClosure","owner":"onmyway133","description":"🍩 Unified communication patterns with easy closure in Swift","archived":false,"fork":false,"pushed_at":"2020-06-11T06:24:26.000Z","size":1205,"stargazers_count":200,"open_issues_count":0,"forks_count":12,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-12-08T03:32:54.033Z","etag":null,"topics":["action","closure","on","swift","target"],"latest_commit_sha":null,"homepage":"https://onmyway133.github.io/","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/onmyway133.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-05-18T19:43:49.000Z","updated_at":"2024-11-02T18:00:15.000Z","dependencies_parsed_at":"2022-08-20T19:50:35.996Z","dependency_job_id":null,"html_url":"https://github.com/onmyway133/EasyClosure","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onmyway133%2FEasyClosure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onmyway133%2FEasyClosure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onmyway133%2FEasyClosure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onmyway133%2FEasyClosure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/onmyway133","download_url":"https://codeload.github.com/onmyway133/EasyClosure/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230431104,"owners_count":18224655,"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":["action","closure","on","swift","target"],"created_at":"2024-09-24T14:12:02.724Z","updated_at":"2024-12-19T12:11:21.416Z","avatar_url":"https://github.com/onmyway133.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# EasyClosure\n\n\n❤️ Support my apps ❤️ \n\n- [Push Hero - pure Swift native macOS application to test push notifications](https://onmyway133.com/pushhero)\n- [PastePal - Pasteboard, note and shortcut manager](https://onmyway133.com/pastepal)\n- [Quick Check - smart todo manager](https://onmyway133.com/quickcheck)\n- [Alias - App and file shortcut manager](https://onmyway133.com/alias)\n- [My other apps](https://onmyway133.com/apps/)\n\n❤️❤️😇😍🤘❤️❤️\n\n[![Version](https://img.shields.io/cocoapods/v/EasyClosure.svg?style=flat)](http://cocoadocs.org/docsets/EasyClosure)\n[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![License](https://img.shields.io/cocoapods/l/EasyClosure.svg?style=flat)](http://cocoadocs.org/docsets/EasyClosure)\n[![Platform](https://img.shields.io/cocoapods/p/EasyClosure.svg?style=flat)](http://cocoadocs.org/docsets/EasyClosure)\n![Swift](https://img.shields.io/badge/%20in-swift%205.0-orange.svg)\n\n![](Screenshots/Artboard.png)\n\n## Table of contents\n\n- [Story](#story)\n- [Target-Action and Delegate](#target-action-and-delegate)\n- [Extensible](#extensible)\n\n## Story\n\nThere are many [Communication patterns](https://www.objc.io/issues/7-foundation/communication-patterns/)\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"https://www.objc.io/images/issue-7/notification-flow-chart-dae4ce12.png\" width=\"500\"/\u003e\n\u003c/div\u003e\n\nSometimes, you just want a unified and quick way to do it. Just call `on` on any `NSObject` subclasses and handle your events the quickest way\n\n### Features\n\n- [x] Shortcut to handle actions and events\n- [x] Easy to extend\n- [x] Correct method suggestion based on generic protocol constraint\n- [x] Support iOS, macOS\n\n### Example\n\n\u003cdiv align = \"center\"\u003e\n\u003cimg src=\"Screenshots/demo.gif\" height=\"300\" /\u003e\n\u003c/div\u003e\n\nWe can make a fun demo of `good, cheap, fast` with `UISwitch`\n\n```swift\nfunc allOn() -\u003e Bool {\n  return [good, cheap, fast].filter({ $0.isOn }).count == 3\n}\n\ngood.on.valueChange { _ in\n  if allOn() {\n    fast.setOn(false, animated: true)\n  }\n}\n\ncheap.on.valueChange { _ in\n  if allOn() {\n    good.setOn(false, animated: true)\n  }\n}\n\nfast.on.valueChange { _ in\n  if allOn() {\n    cheap.setOn(false, animated: true)\n  }\n}\n```\n\n## Target-Action and Delegate\n\n#### UIButton\n\n```swift\nbutton.on.tap {\n  print(\"button has been tapped\")\n}\n```\n\n#### UISlider\n\n```swift\nslider.on.valueChange { value in\n  print(\"slider has changed value\")\n}\n```\n\n#### UITextField\n\n```swift\ntextField.on.textChange { text in\n  print(\"textField text has changed\")\n}\n```\n\n#### UITextView\n\n```swift\ntextView.on.textChange { text in\n  print(\"textView text has changed\")\n}\n```\n\n#### UISearchBar\n\n```swift\nsearchBar.on.textChange { text in\n  print(\"searchBar text has changed\")\n}\n```\n\n#### UIDatePicker\n\n```swift\ndatePicker.on.pick { date in\n  print(\"datePicker has changed date\")\n}\n```\n\n#### UIBarButtonItem\n\n```swift\nbarButtonItem.on.tap {\n  print(\"barButtonItem has been tapped\")\n}\n```\n\n#### UIGestureRecognizer\n\n```swift\ngestureRecognizer.on.occur {\n  print(\"gesture just occured\")\n}\n```\n\n## Extensible\n\nExtend `Container` and specify `Host` to add more functionalities to your own types. For example\n\n```swift\npublic extension Container where Host: UITableView {\n  func cellTap(_ action: @escaping (UITableViewCell) -\u003e Void)) {\n    // Your code here here\n  }\n}\n\n// usage\nlet tableView = UITableView()\ntableView.on.cellTap { cell in\n  \n}\n\n```\n\n## Installation\n\n**EasyClosure** is available through [CocoaPods](http://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod 'EasyClosure'\n```\n\n**EasyClosure** is also available through [Carthage](https://github.com/Carthage/Carthage).\nTo install just write into your Cartfile:\n\n```ruby\ngithub \"onmyway133/EasyClosure\"\n```\n\n**EasyClosure** can also be installed manually. Just download and drop `Sources` folders in your project.\n\n## Author\n\nKhoa Pham, onmyway133@gmail.com\n\n## Contributing\n\nWe would love you to contribute to **EasyClosure**, check the [CONTRIBUTING](https://github.com/onmyway133/EasyClosure/blob/master/CONTRIBUTING.md) file for more info.\n\n## License\n\n**EasyClosure** is available under the MIT license. See the [LICENSE](https://github.com/onmyway133/EasyClosure/blob/master/LICENSE.md) file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonmyway133%2Feasyclosure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fonmyway133%2Feasyclosure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonmyway133%2Feasyclosure/lists"}