Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@objc redundancy when having @objcMembers private dynamic var?

Tags:

swift

realm

So I am using Realm with Swift and I marked my class with the @objcMembers keyword however when I tried to make some private variables, Xcode forced me to add @objc beside those private vars. Is this an intended behavior? Seems like it's redundant to me.

@objcMembers class MyObject: Object {
    @objc dynamic private var text: String = String()
    @objc dynamic private var youtubeLink: String = String()
    @objc dynamic private var count: Int = 0
    dynamic var isFavorite: Bool = false
    dynamic var currentCount: Int = 0
}
like image 856
Tarek Avatar asked Apr 29 '18 08:04

Tarek


People also ask

What is @objc dynamic VAR?

@objc means you want your Swift code (class, method, property, etc.) to be visible from Objective-C. dynamic means you want to use Objective-C dynamic dispatch.

What does @objc do in Swift?

That's where the @objc attribute comes in: when you apply it to a class or method it instructs Swift to make those things available to Objective-C as well as Swift code.

What is dynamic keyword in Swift?

Swift and Objective-C Interoperability Dynamic what? Dynamic dispatch. It simply means that the Objective-C runtime decides at runtime which implementation of a particular method or function it needs to invoke.


1 Answers

The problem is that while @objMembers exposes your members to Objective-C, private hides them again. Thus, to undo that hiding, you have to say @objc explicitly.

To see that this is true, try the following test:

@objcMembers class MyObject: NSObject {
    func f() {
        print("howdy")
    }
}
let c = MyObject()
c.perform(Selector("f"))

That works. But this crashes:

@objcMembers class MyObject: NSObject {
    private func f() {
        print("howdy")
    }
}
let c = MyObject()
c.perform(Selector("f"))

To fix the crash without taking away the private, we have to expose f to Objective-C explicitly:

@objcMembers class MyObject: NSObject {
    @objc private func f() {
        print("howdy")
    }
}
let c = MyObject()
c.perform(Selector("f"))

The only interesting thing about your particular case is that the compiler noticed the problem, instead of letting you just crash as in the second example above. That's because of the dynamic marking, which makes no sense unless we are exposed to Objective-C.

like image 108
matt Avatar answered Nov 06 '22 23:11

matt