Swift : Why is the class method struck out - swift

As long as a Swift class extends from NSObject we can pass it to the Objective-C runtime and ask it to introspect it for us.
We have three options:
class
classForCoder
classForKeyedArchiver
. . however class is struck out. (See image). Why is this?

That's because class is a keyword in Swift, therefore any valid method cannot be named class. In the same way you cannot create a method named for, while or other keyword.
I wasn't able to reproduce the strike-out with my methods, however, naming a method var (or other keyword) in obj-c makes it impossible to be called from Swift.
Edit
I was wrong. It's still possible to call class from Swift using
var clazz: AnyClass? = self.`class`()
However, then the compiler says:
'Class' is unavailable: use 'dynamicType' instead
So the answer by Edwin Vermeers is the correct one.

As you can see in the documentation, it's only available in Objective C and not in swift.
See: https://developer.apple.com/documentation/objectivec/nsobject/1571950-class
I think this is because the AnyObject gives you enough information (More than the NSObject)
for instance you can do NSStringFromClass(BaseObject) in swift instead of the NSStringFromClass([BaseObject class]) that you do in Objective C

Related

Init class deriving from protocol

I've got a class deriving from a simple protocol. It looks like this:
protocol Interface {
func f() -> Void;
}
class TestInterface : Interface {
var arr: [Int] = [];
func f() {
// stuff
}
}
Unfortunately, I can't create this class as Swift has it has no initializers (although the default one would blatantly suffice).
However, the more serious problem is trying to define the initializer. Initially I tried to define an empty initializer. Swift told me that this was illegal because I did not call the super initializer (even though it's a protocol...). Fine, I thought. I called super.init(). Swift then told me this was illegal because the base is a protocol and not a class, so it has no init function. So I can't define an init function because I must call a nonexistent init function inside my own init function. And the normal init function is randomly unavailable for no good reason.
How the hell can I create an instance of my super simple class?
This is actually a totally unrelated issue. The protocol actually used to be a class. For an unrelated reason, the module that this class was imported from crashed the Swift compiler, and corrupted the metadata. So when Swift came to read the metadata for this class/protocol, it was inconsistent and confused the compiler.
As soon as I resolved the issue with the source module (and actually noticed it, thanks crappy XCode error reporting) this was no longer an issue for me.

Do we use RLMObject or Object in Swift Realm?

I've seen examples for Realm where they use
class Person: Object {}
as well as
class Person: RLMObject {}
which one are we supposed to use?
Also, I can't get the init function to work for the former. Any help will be appreciated.
If you're working in Swift, Realm.Object (Object) was designed for the Swift interface. It has better type detection and more natural Swift phrases.
Object is backed by RLMObject, so you can use RLMObject if you want, but its an Objective-C api so some things may be a bit more tedious.
tl;dr
Realm made RealmSwift for a reason! Use Object :)

How do I pass a Swift class to an Objective-C method needing a Class?

I'm looking to use the Objective-C library saxy to parse some XML into objects, however the method signature is:
+ (id)rootXPath:(NSString *)xpath toMany:(Class)toType nsURI:(NSString *)nsURI;
I'm having trouble working out how I'd pass the Class object type as Swift does not seem to work with classes in this way. As a workaround I will probably make the domain model + a wrapper in Objective-C, but would be good to know if there's a way to do it in pure Swift.
I've tried the following, but I get a EXC_BAD_INSTRUCTION:
OXmlElementMapper.rootXPath("/route", toMany: Route.self, nsURI: "")
and this which produces a syntax error:
OXmlElementMapper.rootXPath("/route", toMany: Route.Type, nsURI: "")
MyClass.self is the correct way to reference a class, but perhaps you're missing #objc on the class?
See docs regarding interop

Private property declaration in your class implementation?

Sorry if it's too obvious for you. I'm still learning objetive-c and proper design patterns.
Could you explain me why it is a good idea to declare a property inside #interface in implementation file of a class as a private property? You just can use a local declaration of your type with a class scope, since nobody outside your class would use any getter or setter for this property.
Thanks.
By using the property semantics, you get memory management behavior handled 'for free' by the compiler. Even if your data is private within your class, having the compiler emit correct release/retain/copy saves time and mistakes down the line.
With the modern ARC compiler, this is probably less of an issue now.
When you declare something as #private, usually an instance variable or a property, it became only accessible in methods of the class that declared it. Trying to access it from a subclass results in an error.
I know you didn't asked for this but there is also #protected, when a property is declared like this, it becomes only accessible in methods of the class that declared it and in the methods of any class that inherits from that class.
The source for this info is the best book I know about Objective-C - Learning Objective-C 2.0 by Robert Clair.

Adding methods to an Objective C class interface is optional?

Coming from a C++ background, one thing that confuses me about Objective C is the fact that you can add a method to a class without actually specifying it in the class interface. So I had a barrage of questions:
Why would someone choose to not add the method in the class interface?
Is it simply because of visibility?
Methods without a declaration in the interface are private?
Is declaring methods in a class interface just optional?
Is it different for overriding a base class' method?
The main difference is that C++ sets up much of its inheritance and types at compile time and Objective C does it mostly at runtime.
The only differences in putting a method in the interface (if all parameters are objects) in objective-C are that the compiler can see it at compile time and check that an object could respond to the method - if it does not then you get a warning but the compilation does succeed and the program will run and loo for the method at runtime. If the method is in the implementation of the class or a category (or some other way) then the run time will find it and call it successfully.
There are NO private methods you can call any method.
I believe that this is the only way to create private methods in Objective-C. The language does not support the ability to declare a private method so by not declaring a method in the header file you are making private from all callers.
Proper data encapsulation requires that you lock down access to members that either expose data or manipulates it. Not all members ought to be exposed.
Yes it is.
Yes, this is true.
Yes, this is true as well.
This I am not sure about - perhaps someone with more Objective-C knowledge could answer this one.
Extending Andrew Hare's answer to answer 5, no, it doesn't: whether declared in an #interface or otherwise, method replacement/refinement works the same.