Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Crash casting WKNSURLRequest as? other type

Tags:

I'm getting a hard crash when I try to cast WKNSURLRequest (and other classes, all from the WebKit framework).

e.g. in a playground:

import UIKit
import WebKit

final class Sigh: NSObject { }

NSClassFromString("NSObject") as? Sigh.Type

NSClassFromString("WKNSURLRequest") as? Sigh.Type

The cast from NSObject works (i.e. returns nil), but the cast from WKNSURLRequest crashes with EXC_BAD_ACCESS - I would have assumed that it would return nil as well.

Anyone got any ideas what might be causing this?

like image 845
deanWombourne Avatar asked Mar 28 '17 15:03

deanWombourne


1 Answers

WKNSURLRequest does not inherit from NSObject

@interface WKNSURLRequest : WKObject <NSCopying>

And WKObject is a root class:

NS_ROOT_CLASS
@interface WKObject <WKObject>

Unlike Java, where all classes must inerhit from Object, Obj-C does not require all classes to inherit from NSObject.

The Swift<->Obj-C bridge has explicit support for NSObject and thus also for its subclasses, but I'm not sure it can handle all other root objects equally well. On the export side (Swift classes being exposed to Obj-C) it's not even possible to make an own root class. A swift class that shall be exposed to Obj-C simply must inherit from NSObject, so I'd say that the bridge has not been designed with arbitrary root classes in mind.

Of course, none of this explains the crash, which could just be a simple bug in the Swift compiler or the Swift runtime. As you don't reference the classes statically but just by their name, everything happens at runtime and the Swift runtime may just assume that whatever NSClassFromString returns is a subclass of NSObject and when it then tries to interact with that class, this will fail at runtime because this assumption is plain wrong. In that case it would still be a bug IMHO but it would explain why there is a crash.

like image 146
Mecki Avatar answered Oct 11 '22 14:10

Mecki