{"id":17690218,"url":"https://github.com/onmyway133/rxlifecycle","last_synced_at":"2025-09-20T08:08:54.161Z","repository":{"id":50755105,"uuid":"111124136","full_name":"onmyway133/RxLifeCycle","owner":"onmyway133","description":"🐹 Easy life cycle observation","archived":false,"fork":false,"pushed_at":"2021-05-31T03:38:32.000Z","size":157,"stargazers_count":52,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-09-17T20:15:26.564Z","etag":null,"topics":["application","lifecycle","observation","rxswift","viewcontroller"],"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":"2017-11-17T16:14:01.000Z","updated_at":"2024-11-02T18:02:58.000Z","dependencies_parsed_at":"2022-09-10T18:01:00.452Z","dependency_job_id":null,"html_url":"https://github.com/onmyway133/RxLifeCycle","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/onmyway133/RxLifeCycle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onmyway133%2FRxLifeCycle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onmyway133%2FRxLifeCycle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onmyway133%2FRxLifeCycle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onmyway133%2FRxLifeCycle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/onmyway133","download_url":"https://codeload.github.com/onmyway133/RxLifeCycle/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onmyway133%2FRxLifeCycle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276064355,"owners_count":25578999,"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","status":"online","status_checked_at":"2025-09-20T02:00:10.207Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["application","lifecycle","observation","rxswift","viewcontroller"],"created_at":"2024-10-24T11:50:13.600Z","updated_at":"2025-09-20T08:08:54.141Z","avatar_url":"https://github.com/onmyway133.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RxLifeCycle\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/RxLifeCycle.svg?style=flat)](http://cocoadocs.org/docsets/RxLifeCycle)\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/RxLifeCycle.svg?style=flat)](http://cocoadocs.org/docsets/RxLifeCycle)\n[![Platform](https://img.shields.io/cocoapods/p/RxLifeCycle.svg?style=flat)](http://cocoadocs.org/docsets/RxLifeCycle)\n![Swift](https://img.shields.io/badge/%20in-swift%204.0-orange.svg)\n\n![](Screenshots/Banner.png)\n\n## Description\n\nIf you're using `MVVM` with `FRP`, then chances are that you need to rely on `UIViewController` or `UIApplication` life cycle events to trigger signals. We can either do it by calling a method on the `ViewModel`, like [kickstarter-ios](https://github.com/kickstarter/ios-oss/blob/2b41cfed6a835d7edf34db95c925f7232c17c558/Kickstarter-iOS/Views/Controllers/LoginViewController.swift)\n\n```swift\noverride func viewWillAppear(_ animated: Bool) {\n  super.viewWillAppear(animated)\n  self.viewModel.inputs.viewWillAppear()\n}\n```\n\nor reactively using signal binding.\n\n```swift\noverride func viewDidLoad() {\n  super.viewDidLoad()\n  rx.viewWillAppear.bind(to: viewModel.input.fetchData).disposed(by: disposeBag)\n}\n```\n\nOne way to make observations for the life cycle is to use [sentMessage](https://github.com/ReactiveX/RxSwift/blob/f043778214c8f182018ccdfbf7f440edbe0aecc8/RxCocoa/Foundation/NSObject%2BRx.swift#L136) and [methodInvoked](https://github.com/ReactiveX/RxSwift/blob/f043778214c8f182018ccdfbf7f440edbe0aecc8/RxCocoa/Foundation/NSObject%2BRx.swift#L165) which involve a lot of swizzlings  😱 We shouldn't use swizzlings, it is just asking [for](https://github.com/ReactiveX/RxSwift/issues/1288) [problem](https://blog.newrelic.com/2014/04/16/right-way-to-swizzle/).\n\n```swift\npublic extension Reactive where Base: UIViewController {\n  public var viewWillAppear: ControlEvent\u003c()\u003e {\n    let source = self.methodInvoked(#selector(Base.viewWillAppear)).mapVoid()\n    return ControlEvent(events: source)\n  }\n}\n```\n\nInstead, we can just use simple composition, that you can plug and play everywhere you want. See [demo](https://github.com/onmyway133/RxLifeCycle/tree/master/Example/RxLifeCycleDemo)\n\n## Features\n\n- `ViewControllerLifeCycle` for events related to `UIViewController`\n- `AppLifeCycle` for events related to `UIApplication`, equivalent to `UIApplicationDelegate`\n- Auto clean up upon deinit\n- Support iOS, tvOS\n\n## Usage\n\n### ViewControllerLifeCycle\n\nThis works by embed a child view controller so that it can forward [appearance method](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html)\n\n\u003e After adding a child to a container, the container automatically forwards appearance-related messages to the child\n\nAll you need to do is to declare `ViewControllerLifeCycle` object and observe on it. Remember to keep this `ViewControllerLifeCycle` so it is not released !!\n\n```swift\nlet viewController = LoginViewController()\nlet lifeCycle = ViewControllerLifeCycle(viewController: viewController)\n\n_ = lifeCycle.viewWillAppear.subscribe(onNext: {\n  print(\"viewWillAppear has been called\")\n})\n```\n\nFor convenience, you can also use it directly by using `rxLifeCycle`\n\n```swift\nlet viewController = LoginViewController()\n\n_ = viewController.rxLifeCycle.viewDidAppear.subscribe(onNext: {\n  print(\"viewDidAppear has been called\")\n})\n```\n\nSupported observables\n\n- viewWillAppear\n- viewDidAppear\n- viewWillDisappear\n- viewDidDisappear\n\n### AppLifeCycle\n\nThere are times we need to refresh data when user go back to the app again, which is the `UIApplicationWillEnterForeground` event. All you need to do is to declare `AppLifeCycle` and observe on it. Under the hood, it listens to `UIApplication` notifications and publish the signals.\n\nRemember to keep this `AppLifeCycle` so it is not released !!\n\n```swift\nlet lifeCycle = AppLifeCycle()\n_ = lifeCycle.didBecomeActive.subscribe(onNext: {\n  print(\"didBecomeActive was called\")\n})\n```\n\nFor convenience, you can also use it directly by using `rxLifeCycle` on `UIApplication`\n\n```swift\nlet lifeCycle = AppLifeCycle()\n_ = UIApplication.shared.rxLifeCycle.willEnterForeground.subscribe(onNext: {\n  print(\"willEnterForeground was called\")\n})\n```\n\nSupported observables\n\n- didBecomeActive\n- willResignActive\n- didEnterBackground\n- willEnterForeground\n\n## Installation\n\n**RxLifeCycle** is available through [CocoaPods](http://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod 'RxLifeCycle'\n```\n\n**RxLifeCycle** is also available through [Carthage](https://github.com/Carthage/Carthage).\nTo install just write into your Cartfile:\n\n```ruby\ngithub \"onmyway133/RxLifeCycle\"\n```\n\n**RxLifeCycle** 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 **RxLifeCycle**, check the [CONTRIBUTING](https://github.com/onmyway133/RxLifeCycle/blob/master/CONTRIBUTING.md) file for more info.\n\n## License\n\n**RxLifeCycle** is available under the MIT license. See the [LICENSE](https://github.com/onmyway133/RxLifeCycle/blob/master/LICENSE.md) file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonmyway133%2Frxlifecycle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fonmyway133%2Frxlifecycle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonmyway133%2Frxlifecycle/lists"}