https://github.com/hainayanda/retain
Retain is an object lifecycle helper that provides a simple way to control object retaining and observing it
https://github.com/hainayanda/retain
arc cocoapods combine lifecycle memory propertywrapper publisher retain swift swiftpackage swiftpackagemanager weak
Last synced: over 1 year ago
JSON representation
Retain is an object lifecycle helper that provides a simple way to control object retaining and observing it
- Host: GitHub
- URL: https://github.com/hainayanda/retain
- Owner: hainayanda
- License: mit
- Created: 2023-06-01T03:11:33.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2024-04-04T10:44:58.000Z (about 2 years ago)
- Last Synced: 2025-03-12T17:03:19.818Z (over 1 year ago)
- Topics: arc, cocoapods, combine, lifecycle, memory, propertywrapper, publisher, retain, swift, swiftpackage, swiftpackagemanager, weak
- Language: Swift
- Homepage:
- Size: 237 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Retain
Retain is an object lifecycle helper that provides a simple way to control object retaining and observing it
[](https://app.codacy.com/gh/hainayanda/Retain/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)


[](https://swift.org/package-manager/)
[](https://cocoapods.org/pods/Retain)
[](https://cocoapods.org/pods/Retain)
[](https://cocoapods.org/pods/Retain)
## Example
To run the example project, clone the repo, and run `pod install` from the Example directory first.
## Requirements
- Swift 5.5 or higher
- iOS 13.0 or higher
- MacOS 10.15 or higher
- TVOS 13.0 or higher
- WatchOS 8.0 or higher
- XCode 13 or higher
## Installation
### Cocoapods
Retain is available through [CocoaPods](https://cocoapods.org). To install
it, simply add the following line to your Podfile:
```ruby
pod 'Retain', '~> 1.0.2'
```
### Swift Package Manager from XCode
- Add it using XCode menu **File > Swift Package > Add Package Dependency**
- Add **** as Swift Package URL
- Set rules at **version**, with **Up to Next Major** option and put **1.0.2** as its version
- Click next and wait
### Swift Package Manager from Package.swift
Add as your target dependency in **Package.swift**
```swift
dependencies: [
.package(url: "https://github.com/hainayanda/Retain.git", .upToNextMajor(from: "1.0.2"))
]
```
Use it in your target as a `Retain`
```swift
.target(
name: "MyModule",
dependencies: ["Retain"]
)
```
## Author
hainayanda, hainayanda@outlook.com
## License
Retain is available under the MIT license. See the LICENSE file for more info.
## Usage
### Observe object deallocation
You can observe object deallocation very easily by using the global function `whenDeallocate(for:do:)`:
```swift
let cancellable = whenDeallocate(for: myObject) {
print("myObject is deallocated")
}
```
It will produce Combine's `AnyCancellable` and the closure will be called whenever the object is being deallocated by `ARC`.
If you prefer to get the underlying publisher instead, use `deallocatePublisher(of:)`:
```swift
let myObjectDeallocationPublisher: AnyPublisher = deallocatePublisher(of: myObject)
```
### DeallocateObservable
there's one protocol named `DeallocateObservable` that can expose the global function as a method so it can be used directly from the object itself:
```swift
class MyObject: DeallocateObservable {
...
...
}
```
so then you can do this to the object:
```swift
// get the publisher
let myObjectDeallocationPublisher: AnyPublisher = myObject.deallocatePublisher
// listen to the deallocation
let cancellable = myObject.whenDeallocate {
print("myObject is deallocated")
}
```
### WeakSubject propertyWrapper
There's a `propertyWrapper` that enables `DeallocateObservable` behavior without implementing one named `WeakSubject`:
```swift
@WeakSubject var myObject: MyObject?
```
this `propertyWrapper` will store the object in a weak variable and can be observed like `DeallocateObservable` by accessing its `projectedValue`:
```swift
// get the publisher
let deallocationPublisher: AnyPublisher = $myObject.deallocatePublisher
// listen to the deallocation
let cancellable = $myObject.whenDeallocate {
print("current value in myObject propertyWrapper is deallocated")
}
```
It will always emit an event for as many objects assigned to this `propertyWrapper` as long the object is deallocated when still in this `propertyWrapper`.
### RetainableSubject
`RetainableSubject` is very similar to `WeakSubject`. The only difference is, we can control whether this `propertyWrapper` will retain the object strongly or weak:
```swift
@RetainableSubject var myObject: MyObject?
```
to change the state of the `propertyWrapper` retain state, just access the `projectedValue`:
```swift
// make weak
$myObject.state = .weak
$myObject.makeWeak()
// make strong
$myObject.state = .strong
$myObject.makeStrong()
```
Since `RetainableSubject` is `DeallocateObservable` too, you can do something similar with `WeakSubject`:
```swift
// get the publisher
let deallocationPublisher: AnyPublisher = $myObject.deallocatePublisher
// listen to the deallocation
let cancellable = $myObject.whenDeallocate {
print("current value in myObject propertyWrapper is deallocated")
}
```
## Contribute
You know how, just clone and do a pull request