2

I've tried to use generic type with protocol:

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

protocol SomeProtocol: AnyObject {
    func doSomething()
}

func createWeak(object: SomeProtocol) -> Weak<SomeProtocol> {
    return Weak<SomeProtocol>(value: object)
}

class SomeClass: SomeProtocol {
    func doSomething() {
        print("Some 2")
    }
}

let temp =  SomeClass()
let weakObject = createWeak(object: temp)
weakObject.value?.doSomething()

And got the compiler error: error: 'SomeProtocol' is not convertible to 'AnyObject' return Weak(value: object)

But without AnyObject constraint it works fine

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

protocol Protocol {
    func doSomething()
}

class Class: Protocol {
    func doSomething() {
        print("This is class")
    }
}

func createWeak(object: Protocol) -> Weak<Protocol> {
    return Weak(value: object)
}

let temp =  Class()
let weakObject = createWeak(object: temp)
weakObject.value?.doSomething()

Why I can't use protocols inherited form AnyObject in generic classes?

3
  • This great answer might help you: stackoverflow.com/a/43408193/1974224 Commented Feb 27, 2018 at 18:14
  • "I've tried to use generic type with protocol." And that was your first mistake. :D But quite seriously, it is very tricky to mix generics and protocols, and it is rarely worth the complexity. As @Cristik notes, your approach will not work in Swift. Commented Feb 27, 2018 at 18:20
  • It's worth noting that your Weak doesn't make sense as written. You're not using T. What I think you meant was weak var value: T? and init(value: T). This won't help your underlying problem. As Cristik notes, this entire approach is not possible. You cannot create Weak<SomeProtocol>. The type must be concrete, not a protocol. Commented Feb 27, 2018 at 18:28

1 Answer 1

3

Swift protocols are incomplete types, which means that you can't use them in places like generic arguments, as the compiler needs to know the whole type details so it can allocate the proper memory layout.

Your createWeak function can still be used if you make it generic:

func createWeak<T: SomeProtocol>(object: T) -> Weak<T> {
    return Weak<T>(value: object)
}

The above code works because the compiler will generate at compile time a function mapped to the concrete type you pass.

Even better, you can make the initializer generic, and convert Weak to a struct (value types are preferred Swift over reference ones):

struct Weak<T: AnyObject> {
    weak var value: T?

    init(_ value: T) {
        self.value = value
    }
}

which you can use it instead of the free function:

let weakRef = Weak(temp)
Sign up to request clarification or add additional context in comments.

1 Comment

BTW code without AnyObject constraint in Weak wrapper works fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.