Why can't I declare dynamic variable inside protocol

Viewed 1566

I'm currently working on protocols for my objects which inherits from Realm's Object. Inside my objects I have variables and these variables are marked as @objc dynamic

@objc dynamic var title: String = ""

Now imagine situation that I have more similar objects with same variable title. I want to create protocol for them since I want to have just one generics method for changing title of object.

So, I created protocol with title variable marked as @objc dynamic with the expectation that this is how it works

protocol Titleable: class {
    @objc dynamic var title: String { get set }
}

... this didn't work out and I received actually two errors.

One about marking variable as @objc

@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes

... this I could solve by marking protocol as @objc.

However I still had error connected with dynamic keyword

Only members of classes may be dynamic

... I thought that when I constrained protocol for classes, it should be alright, but... it wasn't.

I somehow solved it by removing @objc as well as dynamic keywords

protocol Titleable: class {
    var title: String { get set }
}

... that works. I'm able to mark variable as @objc dynamic in class where I implement this protocol.

class Item: Object, Titleable {
    @objc dynamic var title: String = ""
}

However, I'm not sure why this works and why marking variable as dynamic inside protocol declaration doesn't. I would appreciate any explanation.

1 Answers

Look at what dynamic means:

dynamic

Apply this modifier to any member of a class that can be represented by Objective-C. When you mark a member declaration with the dynamic modifier, access to that member is always dynamically dispatched using the Objective-C runtime. Access to that member is never inlined or devirtualized by the compiler.

Because declarations marked with the dynamic modifier are dispatched using the Objective-C runtime, they must be marked with the objc attribute.

Particularly consider that first paragraph. It says that something that is marked dynamic cannot be statically dispatched. Now consider the case where I have some class in a module. It's already been compiled, and its methods were statically dispatched. Now consider another module that conforms that class to some protocol that includes a dynamic method. How can that work? The method has already been statically dispatched in some places. It can't retroactively be transformed into dynamic dispatch. (The same can apply to declarations in the same module depending on compiler flags and access levels, but I find it easier to explain cross-module.)

The main reason you'd want to do this in any case is to make sure you can use KVO on that property. (If you have some other reason you need to force conforming types to use a dynamic property, I'm interested to know the use case.) If that is your goal, I would probably require Titleable to conform to NSObjectProtocol.

Related