Skip to content

khamitimur/AmazingWeakSequence

Repository files navigation

AmazingWeakSequence

AmazingWeakSequence is a sequence that holds weak references to its elements.

The problem

In every Swift developer career comes a point when he or she needs to collect weakly referenced objects. But doing so will lead to creating strong references to this objects which is clearly defeats any purpose of having weak references in the first place.

What can you do about it?

First and widely accepted option is to create a wrapper:

class WeakWrapper<T: AnyObject> {
    
    weak var value : T?
    
    init (value: T) {
        self.value = value
    }
}

And then use it like so:

var weakReferences: [WeakWrapper<UIViewController>] = []

// ...

weakReferences.append(WeakWrapper(value: viewController))

// ...

for weakReference in weakReferences {
    guard let value = weakReference.value else { return }
    // ...
}

One problem that is obvious right away: you need to keep track of wrappers with nil values in them. At some point you'll need to clear up your collection or you'll risk to hold a huge number ob objects that are useless.

Is there a better way?

Yes, there is. It's NSHashTable. Take a look at convenience constructor weakObjects():

Returns a new hash table for storing weak references to its contents.

AmazingWeakSequence takes advantage of NSHashTable and adds a sprinkle of thread safety on top.

Usage

import AmazingWeakSequence

protocol ServiceDelegate: AnyObject {
    // ...
}

class Service {
    let delegates = AmazingWeakSequence<ServiceDelegate>()
    
    // ...
    
    func addDelegate(_ delegate: ServiceDelegate) {
        delegates.add(delegate)
    }
    
    func removeDelegate(_ delegate: ServiceDelegate) {
        delegates.remove(delegate)
    }
    
    func notifyDelegates() {
        for delegate in delegates {
            // ...
        }
    }
}

Requirements

  • macOS 10.14+
  • iOS 11.0+
  • tvOS 11.0+
  • watchOS 4.0+
  • Xcode 11+
  • Swift 5.0+

Installation

CocoaPods

To integrate AmazingWeakSequence into your Xcode project using CocoaPods, specify it in your Podfile:

pod 'AmazingWeakSequence', '~> 1.0'

Swift Package Manager

To integrate AmazingWeakSequence into your Xcode project using Swift Package Manager, specify it as dependency in your Package.swift:

dependencies: [
    .package(url: "https://github.com/khamitimur/AmazingWeakSequence.git", .upToNextMajor(from: "1.0.0"))
]

License

This project is licensed under the MIT License.

Acknowledgments