AnyClass is NSObjectProtocol ... sometimes?

Following this question , I really liked the described behavior, and I conducted some investigation, which left me rather puzzled.

Problem

Checking the values NSObjectProtocolto return NSClassFromStringreturns true in any case, except for the return NSClassFromString("WKNSURLRequest"). The fact that all the results are correct is a bit surprising for PureClassand SwiftObject.

import UIKit
import WebKit
import ObjectiveC

class Sigh: NSObject { }
class PureClass { }

let sighClass = NSClassFromString(NSStringFromClass(Sigh.self))!
let pureClass = NSClassFromString(NSStringFromClass(PureClass.self))!
let nsObject = NSClassFromString("NSObject")!
let wkRequestClass = NSClassFromString("WKNSURLRequest")!
let swiftObject = NSClassFromString("SwiftObject")!

print("\n*NSObjectProtocol CONFORMANCE*")
print("NSObject: ", nsObject is NSObjectProtocol)
//print("WkRequestClass: ", wkRequestClass is NSObjectProtocol)
print("WkRequestClass: This would crash")
print("SighClass: ", sighClass is NSObjectProtocol)
print("PureClass: ", pureClass is NSObjectProtocol)
print("SwiftObject: ", swiftObject is NSObjectProtocol)

We are not checking an instance of these classes, but returning NSClassFromStringwhich is AnyClass ?.

AnyClass is a typedef for AnyObject.Type. Why is this NSObjectProtocol? Why not for WkRequestClass?

mecki , , webkit: WKNSURLRequest WKObject, , NSObjectProtocol, WKObject WKObject (), NSObject ().

@protocol WKObject <NSObject>

@property (readonly) API::Object& _apiObject;

@end

NS_ROOT_CLASS
@interface WKObject <WKObject>

- (NSObject *)_web_createTarget NS_RETURNS_RETAINED;

@end

: https://github.com/WebKit/webkit/blob/master/Source/WebKit2/Shared/Cocoa/WKObject.h

- , - . :

//: Playground - noun: a place where people can play

import UIKit
import WebKit
import ObjectiveC

class Sigh: NSObject { }
class PureClass { }

let sighClass: AnyClass = NSClassFromString(NSStringFromClass(Sigh.self))!
let pureClass: AnyClass = NSClassFromString(NSStringFromClass(PureClass.self))!
let nsObject: AnyClass = NSClassFromString("NSObject")!
let wkRequestClass: AnyClass = NSClassFromString("WKNSURLRequest")!
let swiftObject: AnyClass = NSClassFromString("SwiftObject")!

print("\n*NSObjectProtocol CONFORMANCE*")
print("NSObject: ", nsObject is NSObjectProtocol)
//print("WkRequestClass: ", wkRequestClass is NSObjectProtocol)
print("WkRequestClass: This would crash")
print("SighClass: ", sighClass is NSObjectProtocol)
print("PureClass: ", pureClass is NSObjectProtocol)
print("SwiftObject: ", swiftObject is NSObjectProtocol)

print("\n*ANYCLASS PRINT*")
print("NSObject: ", nsObject)
print("WkRequestClass: ", wkRequestClass)
print("SighClass: ", sighClass)
print("PureClass: ", pureClass)
print("SwiftObject: ", swiftObject)

print("\n*TYPE PRINT*")

print("Type of NSObject: ", type(of: nsObject))
print("Type of WkRequestClass: ", type(of: wkRequestClass))
print("Type of SighClass: ", type(of: sighClass))
print("Type of PureClass: ", type(of: pureClass))
print("Type of SwiftObject: ", type(of: swiftObject))

print("\n*.SELF PRINT*")

print("NSObject.self: ", nsObject.self)
print("WkRequestClass.self: ", wkRequestClass.self)
print("SighClass.self: ", sighClass.self)
print("PureClass.self: ", pureClass.self)
print("SwiftObject.self: ", swiftObject.self)

print("\n*SUPERCLASS PRINT*")

print("NSObject superClass: ", nsObject.superclass() ?? "nil")
//print("WkRequestClass superClass: ", wkRequestClass.superclass())
print("WkRequestClass superClass: This would crash")
print("SighClass superClass: ", sighClass.superclass() ?? "nil")
print("PureClass superClass: ", pureClass.superclass() ?? "nil")
print("SwiftObject superClass: ", swiftObject.superclass() ?? "nil")

print("\n*INTROSPECTION*\n")

var count: UInt32 = 0
var protocols = class_copyProtocolList(wkRequestClass, &count);

for i: Int in 0..<Int(count) {
    print("WkRequestClass implements", protocols![i]!)
}

print("WkRequestClass superClass is", class_getSuperclass(wkRequestClass))
print("Its super super class is", class_getSuperclass(class_getSuperclass(wkRequestClass)))

//Introspecting WKObject
protocols = class_copyProtocolList(class_getSuperclass(wkRequestClass), &count);

for i: Int in 0..<Int(count) {
    print("WKObject implements", protocols![i]!)
}

print("WKObject conforms the NSObjectProtocol? ", class_conformsToProtocol(class_getSuperclass(wkRequestClass), NSObjectProtocol.self))

, WKNSURLRequest WKObject objective-c runtime.

- , , . .

:

**NSObjectProtocol CONFORMANCE**

 - NSObject:  true 
 - WkRequestClass: This would crash 
 - SighClass:  true
 - PureClass:  true 
 - SwiftObject:  true

**ANYCLASS PRINT**

 - NSObject:  NSObject
 - WkRequestClass:  WKNSURLRequest
 - SighClass:  Sigh
 - PureClass:  PureClass
 - SwiftObject:  SwiftObject

**TYPE PRINT**

 - Type of NSObject:  NSObject.Type
 - Type of WkRequestClass:  WKNSURLRequest.Type
 - Type of SighClass:  Sigh.Type
 - Type of PureClass:  PureClass.Type
 - Type of SwiftObject:  SwiftObject.Type

**.SELF PRINT**

 - NSObject.self:  NSObject
 - WkRequestClass.self:  WKNSURLRequest
 - SighClass.self:  Sigh
 - PureClass.self:  PureClass
 - SwiftObject.self:  SwiftObject

**SUPERCLASS PRINT**

 - NSObject superClass:  nil
 - WkRequestClass superClass: This would crash
 - SighClass superClass:  NSObject
 - PureClass superClass:  SwiftObject
 - SwiftObject superClass:  nil

**INTROSPECTION**

 - WkRequestClass implements ``
 - WkRequestClass superClass is WKObject
 - Its super super class is nil
 - WKObject implements ``
 - WKObject conforms the NSObjectProtocol?  true

,

wkRequestClass.isSubclass(of: class_getSuperclass(wkRequestClass))

, .

, c / ? ( ), , , WKObject NSObjectProtocol, , . .

. ? -, , ? .

+1
1

, WKObject NSObject protocol, WKObject protocol, NSObject protocol. .

, +isSubclassOfClass: +instancesRespondToSelector:, NSObject, NSObject class , , NSObject, sub - NSObject. , NSObject , NSObject .

unit test:

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

2:

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

2, 3 . , Swift- Swift, Objective-C . Objective-C, .

, WKObject +conformsToProtocol: ( 1 ), , NSObject protocol, +instancesRespondToSelector: +isSubclassOfClass:, , . , NSObject, , . , ; - " w90 > ", : , , ; objc_msgSend() ( , ), .

, -, Swift . Obj-C Swift , , NSObject , . Swift Objective-C , NSObject. . Swift , , . , ​​Swift-Objc-Bridge .

1:

:

, swift, NSObjectProtocol, ?

, Quicktime Runtime. Swift NSObjectProtocol. , . .

:

, , NSObjectProtocol, PureClass , PureClass NSObjectProtocol

, PureClass NSObjectProtocol ; . fooobar.com/questions/196114/...

, NSObjectProtocol

func `self`() -> Self

Swift, , , :

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

, Swift Obj-C, .

Swift :

, @objc , Objective-C @objc.

@objc NSObject, Swift.

+1

Source: https://habr.com/ru/post/1673421/


All Articles