type A requires that type B be a class type swift 4

As you see, ServiceDelegate is a protocol, not a class type. Even if all types which can conform to ServiceDelegate 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:

@objc protocol ServiceDelegate {
    func doIt()
}

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.


The problem is that WeakReference<ServiceDelegate> is wrong at line

private var observers = [WeakReference<ServiceDelegate>]()

You have to use a concrete class instead of protocol inside <>

You have two possible solutions:

  1. Create a concrete class and use it:
class ServiceClass: ServiceDelegate {
//...
}
private var observers = [WeakReference<ServiceClass>]()
  1. Or use a protocol. I mean this:

     final class WeakReference<T: AnyObject> {
    
         private(set) weak var value: T?
    
         init(value: T?) {
             self.value = value
         }
     }
    
     protocol SomeContainer: AnyObject { }
     extension WeakReference: SomeContainer { }
    

and use this way:

 private var observers = [SomeContainer]()

Note

Using this way:

class SomeClass<T: ServiceDelegate> {
    private var observers = [WeakReference<T>]()
}

You just move the problem to another part of the code.


You can't have a WeakReference<ServiceDelegate>. ServiceDelegate itself is not an AnyObject, it just requires that anything that conforms to it be an AnyObject.

You would need to make SomeClass generic and use the generic type as the type for the WeakReference:

class SomeClass<T: ServiceDelegate> {
    private var observers = [WeakReference<T>]()
}

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 on WeakReference:

final class WeakServiceDelegate {
    private(set) weak var value: ServiceDelegate?

    init(value: ServiceDelegate?) {
        self.value = value
    }
}

class SomeClass {
    private var observers = [WeakServiceDelegate]()
}

Alternatively you could make WeakReference conditionally conform to ServiceDelegate:

extension WeakReference: ServiceDelegate where T: ServiceDelegate {
    func doIt() {
        value?.doIt()
    }
}

And then use an array of ServiceDelegate in SomeClass:

class SomeClass {
    private var observers = [ServiceDelegate]()

    func addObserver<T: ServiceDelegate>(_ observer: T) {
        observers.append(WeakReference(value: observer))
    }
}

Tags:

Swift

Swift4