{"id":26275694,"url":"https://github.com/hainayanda/retain","last_synced_at":"2025-03-14T10:17:37.284Z","repository":{"id":171732016,"uuid":"648019183","full_name":"hainayanda/Retain","owner":"hainayanda","description":"Retain is an object lifecycle helper that provides a simple way to control object retaining and observing it","archived":false,"fork":false,"pushed_at":"2024-04-04T10:44:58.000Z","size":243,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-12T17:03:19.818Z","etag":null,"topics":["arc","cocoapods","combine","lifecycle","memory","propertywrapper","publisher","retain","swift","swiftpackage","swiftpackagemanager","weak"],"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/hainayanda.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,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-06-01T03:11:33.000Z","updated_at":"2023-07-24T11:59:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"eaa3e56b-4101-4b3b-92f7-ded803cdf10c","html_url":"https://github.com/hainayanda/Retain","commit_stats":null,"previous_names":["hainayanda/retain"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hainayanda%2FRetain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hainayanda%2FRetain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hainayanda%2FRetain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hainayanda%2FRetain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hainayanda","download_url":"https://codeload.github.com/hainayanda/Retain/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243558441,"owners_count":20310574,"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":["arc","cocoapods","combine","lifecycle","memory","propertywrapper","publisher","retain","swift","swiftpackage","swiftpackagemanager","weak"],"created_at":"2025-03-14T10:17:36.749Z","updated_at":"2025-03-14T10:17:37.278Z","avatar_url":"https://github.com/hainayanda.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Retain\n\nRetain is an object lifecycle helper that provides a simple way to control object retaining and observing it\n[![Codacy Badge](https://app.codacy.com/project/badge/Grade/42316a3fbf084bf7bb44869f6c8d827b)](https://app.codacy.com/gh/hainayanda/Retain/dashboard?utm_source=gh\u0026utm_medium=referral\u0026utm_content=\u0026utm_campaign=Badge_grade)\n![build](https://github.com/hainayanda/Retain/workflows/build/badge.svg)\n![test](https://github.com/hainayanda/Retain/workflows/test/badge.svg)\n[![SwiftPM Compatible](https://img.shields.io/badge/SwiftPM-Compatible-brightgreen)](https://swift.org/package-manager/)\n[![Version](https://img.shields.io/cocoapods/v/Retain.svg?style=flat)](https://cocoapods.org/pods/Retain)\n[![License](https://img.shields.io/cocoapods/l/Retain.svg?style=flat)](https://cocoapods.org/pods/Retain)\n[![Platform](https://img.shields.io/cocoapods/p/Retain.svg?style=flat)](https://cocoapods.org/pods/Retain)\n\n## Example\n\nTo run the example project, clone the repo, and run `pod install` from the Example directory first.\n\n## Requirements\n\n- Swift 5.5 or higher\n- iOS 13.0 or higher\n- MacOS 10.15 or higher\n- TVOS 13.0 or higher\n- WatchOS 8.0 or higher\n- XCode 13 or higher\n\n## Installation\n\n### Cocoapods\n\nRetain is available through [CocoaPods](https://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod 'Retain', '~\u003e 1.0.2'\n```\n\n### Swift Package Manager from XCode\n\n- Add it using XCode menu **File \u003e Swift Package \u003e Add Package Dependency**\n- Add **\u003chttps://github.com/hainayanda/Retain.git\u003e** as Swift Package URL\n- Set rules at **version**, with **Up to Next Major** option and put **1.0.2** as its version\n- Click next and wait\n\n### Swift Package Manager from Package.swift\n\nAdd as your target dependency in **Package.swift**\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/hainayanda/Retain.git\", .upToNextMajor(from: \"1.0.2\"))\n]\n```\n\nUse it in your target as a `Retain`\n\n```swift\n .target(\n    name: \"MyModule\",\n    dependencies: [\"Retain\"]\n)\n```\n\n## Author\n\nhainayanda, hainayanda@outlook.com\n\n## License\n\nRetain is available under the MIT license. See the LICENSE file for more info.\n\n## Usage\n\n### Observe object deallocation\n\nYou can observe object deallocation very easily by using the global function `whenDeallocate(for:do:)`:\n\n```swift\nlet cancellable = whenDeallocate(for: myObject) {\n    print(\"myObject is deallocated\")\n}\n```\n\nIt will produce Combine's `AnyCancellable` and the closure will be called whenever the object is being deallocated by `ARC`.\n\nIf you prefer to get the underlying publisher instead, use `deallocatePublisher(of:)`:\n\n```swift\nlet myObjectDeallocationPublisher: AnyPublisher\u003cVoid, Never\u003e = deallocatePublisher(of: myObject)\n```\n\n### DeallocateObservable\n\nthere's one protocol named `DeallocateObservable` that can expose the global function as a method so it can be used directly from the object itself:\n\n```swift\nclass MyObject: DeallocateObservable { \n    ...\n    ...\n}\n```\n\nso then you can do this to the object:\n\n```swift\n// get the publisher\nlet myObjectDeallocationPublisher: AnyPublisher\u003cVoid, Never\u003e = myObject.deallocatePublisher\n\n// listen to the deallocation\nlet cancellable = myObject.whenDeallocate {\n    print(\"myObject is deallocated\")\n}\n```\n\n### WeakSubject propertyWrapper\n\nThere's a `propertyWrapper` that enables `DeallocateObservable` behavior without implementing one named `WeakSubject`:\n\n```swift\n@WeakSubject var myObject: MyObject?\n```\n\nthis `propertyWrapper` will store the object in a weak variable and can be observed like `DeallocateObservable` by accessing its `projectedValue`:\n\n```swift\n// get the publisher\nlet deallocationPublisher: AnyPublisher\u003cVoid, Never\u003e = $myObject.deallocatePublisher\n\n// listen to the deallocation\nlet cancellable = $myObject.whenDeallocate {\n    print(\"current value in myObject propertyWrapper is deallocated\")\n}\n```\n\nIt will always emit an event for as many objects assigned to this `propertyWrapper` as long the object is deallocated when still in this `propertyWrapper`.\n\n### RetainableSubject\n\n`RetainableSubject` is very similar to `WeakSubject`. The only difference is, we can control whether this `propertyWrapper` will retain the object strongly or weak:\n\n```swift\n@RetainableSubject var myObject: MyObject?\n```\n\nto change the state of the `propertyWrapper` retain state, just access the `projectedValue`:\n\n```swift\n// make weak\n$myObject.state = .weak\n$myObject.makeWeak()\n\n// make strong\n$myObject.state = .strong\n$myObject.makeStrong()\n```\n\nSince `RetainableSubject` is `DeallocateObservable` too, you can do something similar with `WeakSubject`:\n\n```swift\n// get the publisher\nlet deallocationPublisher: AnyPublisher\u003cVoid, Never\u003e = $myObject.deallocatePublisher\n\n// listen to the deallocation\nlet cancellable = $myObject.whenDeallocate {\n    print(\"current value in myObject propertyWrapper is deallocated\")\n}\n```\n\n## Contribute\n\nYou know how, just clone and do a pull request\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhainayanda%2Fretain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhainayanda%2Fretain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhainayanda%2Fretain/lists"}