Reputation: 955
I have a generic struct declared as follows:
struct WeakReference<T: AnyObject> {
weak var value: T?
init(value: T?) {
self.value = value
}
}
And a protocol:
protocol SomeProtocol: class {
}
But I'm not able to declare a variable of type of WeakReference<SomeProtocol>
, the compiler complains that
'WeakReference' requires that
SomeProtocol
be a class type
Interestingly, in Swift, the class
is a typealias of AnyObject.
I actually want to hold an array of WeakReference<SomeProtocol>
because the array holds strong references.
Class-only generic constraints in Swift is a similar question but doesn't really solve this problem.
How can we pass the SomeProtocol
to WeakReference
?
EDIT: The following scenario compiles fine, but we lose the ability to hold weak reference:
struct Reference<T> {
var value: T?
init(value: T?) {
self.value = value
}
}
var array: [Reference<SomeProtocol>] = []
Upvotes: 6
Views: 1380
Reputation: 519
I think this should solve your problem.
struct WeakReference<T> {
private weak var privateRef: AnyObject?
var ref: T? {
get { return privateRef as? T }
set { privateRef = newValue as AnyObject }
}
init(_ ref: T? = nil) {
self.ref = ref
}
}
// usage
protocol MyProto: class { }
extension UIViewController: MyProto { }
let vc = UIViewController()
var weakRef = WeakReference<MyProto>(vc)
print(weakRef.ref)
You obviously can use WeakReference
with non class protocol or non bridged value types.
If you try that, you'll get always nil
.
P.S. : Try this code on a real Xcode project because in the Playground doesn't work as expected.
Upvotes: 1
Reputation: 408
What do you think about this approach?
class WeakReference<T> {
weak var value: AnyObject?
init(value: T?) {
self.value = value as? AnyObject
}
}
protocol SomeProtocol: class {
}
class A: SomeProtocol { }
let araayOfSomeProtocolObjects: [SomeProtocol] = (0...5).map {_ in A() }
let arrayOfWeakReferences: [WeakReference<SomeProtocol>] = araayOfSomeProtocolObjects.map { WeakReference(value: $0) }
for item in arrayOfWeakReferences {
print(item.value is A) // true
}
Upvotes: 1
Reputation: 780
Thats simple. You are passing SomeProtocol
which is a protocol
. You need to pass there specific class type.
Eample:
class SomeImplementation: SomeProtocol {
}
var weakSome: WeakReference<SomeImplementation> = ...
Or you can bypass it by marking the protocol with @objc
annotation, but I am not a fan of this approach.
@objc protocol SomeProtocol: class {
}
var weakSome: WeakReference<SomeProtocol> = ...
Try checking this answer, it might provide you more context on the issue.
Upvotes: 1