Type a Requires That Type B Be a Class Type Swift 4

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

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))
}
}

Pass a class type for use inside a method

How about the generic Swift way.

The code constrains the generic type T to MyClass since it must have a name property.

class MyClass : NSObject {
var name : String

override required init() {
self.name = ""
super.init()
}
}

class OneClass : MyClass {
required init() {
super.init()
self.name = "One"
}
}

class TwoClass : MyClass {
required init() {
super.init()
self.name = "Two"
}
}

class Thing : NSObject {
func doStuff<T : MyClass>(withClass cls: T.Type) -> String {
let x = cls.init()
return x.name
}
}

let z = Thing()
print(z.doStuff(withClass: OneClass.self))
print(z.doStuff(withClass: TwoClass.self))

Or use a protocol.

protocol Nameable {
var name : String { get }
init()
}

class MyClass : NSObject, Nameable { ...

...

class Thing : NSObject {
func doStuff<T : Nameable>(withClass cls: T.Type) -> String {
let x = cls.init()
return x.name
}
}

How to make protocol conformed by only required classes?

I am not sure if below code is what you need, do let me know if that’s what you were looking for, else I will be happy to remove my answer.

protocol A:BaseViewController  {
func execute()
}

protocol B:A {
func confirm()
}

class BaseViewController: UIViewController {

}

class AnotherVC: B {

}

In above code compiler will give error saying-:

'A' requires that 'AnotherVC' inherit from ‘BaseViewController'

Once you inherit AnotherVC from BaseViewController, it will give another error saying-:

Type 'AnotherVC' does not conform to protocol ‘A'

Once you confirm the implementations errors will be resolved-:

class AnotherVC:BaseViewController, B {
func confirm() {

}

func execute() {

}

}

Type specific method is unavailable for a var returned with `some` directive

The return type of the method is some TransportProtocol, not Car. So even though the returned instance is of type Car, you cannot call any methods on it that only exist on Car, but not on TransportProtocol.

The runtime knows that the concrete type of someTransport is Car, but the compiler only knows that the return type conforms to TransportProtocol.

If you want to be able to access Car methods on someTransport, you need to downcast it to Car.

if let car = someTransport as? Car {
car.changeOil()
}

Using the some keyword has type-system benefits when used for opaque returns types (introduced in SE-0244 as part of Swift 5.1), since it actually enables returning a protocol with associated types without having to explicitly make the method generic. This is what drives SwiftUI, since it enables you to return some View.

On the other hand, using opaque return types for protocols without associated types holds no benefits, so in your particular example, there's no reason to use it.

Why using Self as return type is not considered as the protocol's constraint?

Because it's not useful to have a Self as a parameter type of a method. Suppose that you can do:

protocol P {
func f(_ x: Self)
}

class A: P {
func f(_ x: Self) {
// not relevant
}
}

class B: A { }

Now suppose I have:

func g(x: A) {
// what can I do with x?
}

The fact is, there is no way to call x.f. Because I can pass an instance of B to x, in which case x.f would accept a B instead. x could be an instance of any subclass of A that I have no way of knowing at compile time, so I don't know what I can pass to x.f.


Compare that to Self used as the return type:

protocol P {
func f() -> Self
}

// Implementation:
class A: P {
func f() -> Self {
self
}
}

class B: A { }

func g(x: A) {
let foo: A = x.f()
}

Here, we know that I can at least assign the return value of x.f to a variable of type A. Even if x is an instance of B, which means that f returns a B, we can still assign that to a variable of type A.



Related Topics



Leave a reply



Submit