How Does Anyobject Conform to Nsobjectprotocol

How Does AnyObject Conform to NSObjectProtocol?

In the Cocoa / Objective-C world, AnyObject is id. Having cast this object to AnyObject, you can send any known Objective-C message to it, such as isKindOfClass or conformsToProtocol. Now, when you say isKindOfClass or conformsToProtocol, you're not in the Swift world any more; you're talking to Cocoa with Objective-C. So think about how Objective-C sees this object. All classes in the Objective-C world descend from some base class; a baseless class like MyClass is impossible. And every base class in the Objective-C world conforms to the NSObject protocol (which Swift calls NSObjectProtocol); that's what it is to be (or descend from) a base class! Therefore, to get it into the Objective-C world, Swift presents MyClass as descending from a special bridging base class SwiftObject which does indeed conform to NSObjectProtocol (as you can see here: https://github.com/apple/swift/blob/master/stdlib/public/runtime/SwiftObject.mm).

Swift class/struct implicitly conforms to NSObjectProtocol?

Apparently, it’s both bug and feature. https://bugs.swift.org/browse/SR-10495

Can someone explain difference between class and NSObjectProtocol

Only Object or Instance type can conform to both type of protocol, where Structure and Enum can't conform to both the type

But the major difference is:
If one declares a protocol like below means it is inheriting NSObjectProtocol

protocol ViewDelegate: NSObjectProtocol { 
func someFunc()
}

if the conforming class is not a child class of NSObject then that class need to have the NSObjectProtocol methods implementation inside it. (Generally, NSObject does conform to NSObjectProtocol)

ex:

class Test1: NSObject, ViewDelegate {
func someFunc() {
}
//no need to have NSObjectProtocol methods here as Test1 is a child class of NSObject
}

class Test2: ViewDelegate {
func someFunc() {
}
//Have to implement NSObjectProtocol methods here
}

If one declare like below, it means only object type can conform to it by implementing its methods. nothing extra.

protocol ViewDelegate: class { 
func someFunc()
}

Type CCC doesnt conform to protocol 'NSObjectProtocol'

If you follow up the inheritance chain, NSURLSessionDataDelegate inherits NSURLSessionTaskDelegate, which inherits NSURLSessionDelegate, which inherits, NSObjectProtocol. This protocol has various required methods like isEqual(_:) and respondsToSelector(_:) which you class does not implement.

Generally what you would do here is make your class inherit NSObject which conforms to NSObjectProtocol:

class Test: NSObject, NSURLSessionDataDelegate {
...
}

When is a variable a AnyObject but not a NSObject

On platforms with Objective-C compatibility (which means all of Apple's platforms and no others), every class type is (secretly) a subclass of the SwiftObject class, which provides NSObject protocol conformance.

On other platforms, NSObject is “just another class”, implemented in Swift, so only a class that explicitly has NSObject as a superclass has instances that are NSObjects.

Swift : Type XXX must conform to protocol 'NSObjectProtocol'

Self answered for sake of archiving.

When adding

override func isEqual(anObject: AnyObject?) -> Bool {
return super.isEqual(anObject)
}

to my class, it works.
This method should have been inherited from the base class.

Looks like a bug in Swift / Xcode 6.1 to me

AnyClass is NSObjectProtocol... sometimes?

You are correct that WKObject implements the NSObject protocol as it implements the WKObject protocol and this protocol inherits from the NSObject protocol. But that plays no role here.

Certain methods like +isSubclassOfClass: or +instancesRespondToSelector: are not declared in the NSObject protocol, these are just normal class methods of the NSObject class and thus inherited by all sub-classes of NSObject but only by sub-classes of NSObject. Other root classes must implement these themselves if they want to be NSObject compatible, the NSObject protocol won't force them to do so.

Now check out this code from a unit test class:

SEL issubclasssel = @selector(isSubclassOfClass:);
Protocol * nsobjp = @protocol(NSObject);
Class c1 = NSClassFromString(@"NSObject");
XCTAssert(c1);
XCTAssert([c1 conformsToProtocol:nsobjp]);
XCTAssert([c1 instancesRespondToSelector:issubclasssel]);
XCTAssert([c1 isSubclassOfClass:[NSObject class]]);

Class c2 = NSClassFromString(@"WKNSURLRequest");
XCTAssert(c2);
XCTAssert([c2 conformsToProtocol:nsobjp]); // Line 1
XCTAssert([c2 instancesRespondToSelector:issubclasssel]); // Line 2
XCTAssert([c2 isSubclassOfClass:[NSObject class]]); // Line 3

This code crashes at Line 2:

Thread 1: EXC_BAD_ACCESS (code=1, address=0x18)

And if I comment out Line 2, the code still crashes at Line 3 with exactly the same error. Note that this is not Swift code, nor in any way Swift related, this is pure Objective-C code. It's just wrong Objective-C code, as you will see below.

So WKObject does implement +conformsToProtocol: (Line 1 does not crash), it has to, as this is a requirement of the NSObject protocol, but it doesn't implement +instancesRespondToSelector: or +isSubclassOfClass:, and it doesn't have to, so this is perfectly okay. It is a root class, it doesn't inherit from NSObject and there is no protocol that would require it to implement any of these. It was my mistake above to call these methods; calling not-existing methods on objects is "undefined behavior" and this allows the runtime pretty much anything: ignoring the call, just logging an error, throwing an exception, or just crashing right away; and as objc_msgSend() is a highly optimized function (it has no security checks, that would too expensive for every call), it just crashes.

But apparently Swift sometimes doesn't seem to care. When dealing with Obj-C objects, Swift seems to assume that it can always call one of theses methods that NSObject and any sub-class of it implement, even though no protocol would promise that. And that's why certain Swift code constructs cause a crash with Objective-C root objects that don't inherit from NSObject. And as this assumption is simply wrong. Swift must never call any methods on root objects where it doesn't know for sure that these methods are also implemented. Thus I called this a bug in the Swift-Objc-Bridge at the other question.

Update 1:

Giuseppe Lanza asked:

Why then when I have a pure swift class, I get the class from string
and then I test is NSObjectProtocol I get true?

Personally I think this is also a bug in the Swift Runtime. A pure Swift class does not conform to the NSObjectProtocol. Actually it cannot even conform to it, see answer below.

Giuseppe Lanza asked:

Please note that if I create a protocol that inherits from
NSObjectProtocol and then I try to make PureClass conformance to that
protocol the compiler will complain that PureClass is not
NSObjectProtocol compliant

That's because PureClass would have to implement all required NSObjectProtocol methods to conform to that protocol; see this answer https://stackoverflow.com/a/24650406/15809

However, it cannot even satisfy that requirement, as one requirement of NSObjectProtocol is to implement this method

func `self`() -> Self

and that's simply not possible for a pure Swift class, as when you try to do that, the compiler will complain:

error: method cannot be an implementation of an @objc requirement
because its result type cannot be represented in Objective-C

which is correct, a pure Swift class cannot be represented in Obj-C, so it cannot return the required type.

The Swift documentation also says:

Note that @objc protocols can be adopted only by classes that
inherit from Objective-C classes or other @objc classes.

And currently @objc forces you to inherit from NSObject, which a pure Swift class does not.



Related Topics



Leave a reply



Submit