the following code gives me a compile error
'WeakReference' requires that 'ServiceDelegate' be a class type
protocol ServiceDelegate: AnyObject {
func doIt()
}
class SomeClass() {
// compile error occurs in this line
private var observers = [WeakReference<ServiceDelegate>]()
}
WeakReference code:
final class WeakReference<T: AnyObject> {
private(set) weak var value: T?
init(value: T?) {
self.value = value
}
}
How can I fix this error? Delegate should be declared correctly as per this site.
What I have tried so far:
- Changing the delegate protocol conformance from
AnyObject
toclass
does not solve the problem. - Try the above code in a clean playground.
The problem is that
WeakReference<ServiceDelegate>
is wrong at lineprivate var observers = [WeakReference<ServiceDelegate>]()
You have to use a concrete class instead of protocol inside
<>
You have two possible solutions:
Or use a protocol. I mean this:
and use this way:
Note
Using this way:
You just move the problem to another part of the code.
I had similar problem and ended up keeping generic
WeakReference
, but removing type constraint:This works for classes, Objective-C protocols and Swift protocols:
Unfortunately it compiles for other things too:
In Swift anything can be casted to
AnyObject
, but for value types that means boxing - new instance is allocated and immediately lost, so it always produces nil.This can be used to implement an assertion that casting to
AnyObject
preserves identity:Alternative approach would be to use https://github.com/wickwirew/Runtime to validate kind of
T.self
.You can't have a
WeakReference<ServiceDelegate>
.ServiceDelegate
itself is not anAnyObject
, it just requires that anything that conforms to it be anAnyObject
.You would need to make
SomeClass
generic and use the generic type as the type for theWeakReference
:If the generic on
SomeClass
is too constricting and you want to be able to have instances of multiple unrelated classes as observers then I would do it by abandoning the generic parameter onWeakReference
:Alternatively you could make
WeakReference
conditionally conform toServiceDelegate
:And then use an array of
ServiceDelegate
inSomeClass
:As you see,
ServiceDelegate
is a protocol, not a class type. Even if all types which can conform toServiceDelegate
are class types,ServiceDelegate
itself is not a class type. It is the fact of the pure Swift protocols currently.Try
@obc
, Objective-C protocols are a bit different:You may want to exclude Objective-C something and to make some pure Swift classes conform to
ServiceDelegate
, but I cannot find other ways around.create plain protocol
inherit associatedtype protocol from AnyWeakValue
create class Weak inherit WeakValue
using example