wickwirew / Runtime

A Swift Runtime library for viewing type info, and the dynamic getting and setting of properties.
MIT License
1.08k stars 94 forks source link

Add support for Swift objects inherited from objective-c classes #103

Open anton-plebanovich opened 2 years ago

anton-plebanovich commented 2 years ago

Hi, I tried to use the Runtime and faced an issue with an object that inherits from the UIView. Property offsets were wrong. When I dug deeper I found that offsets don't count the instance size of UIView itself. I was able to workaround by modifying ClassMetadata's toTypeInfo() method like this:

mutating func toTypeInfo() -> TypeInfo {
    var info = TypeInfo(metadata: self)
    info.mangledName = mangledName()
    info.properties = properties()
    info.genericTypes = Array(genericArguments())

    var _sc: ClassMetadata? = self
    while var sc = _sc?.superClassMetadata()?.asClassMetadata() {
        info.inheritance.append(sc.type)
        let superInfo = sc.toTypeInfo()
        info.properties.append(contentsOf: superInfo.properties)
        _sc = sc
    }

    // Fix offset because of the obj-c inheritance if needed.
    // Fix own properties only.
    if let sc = _sc, let superClass = pointer.pointee.superClass as? AnyObject.Type {
        let size = class_getInstanceSize(superClass) - class_getInstanceSize(NSObject.self)
        for i in 0..<numberOfFields() {
            info.properties[i].offset += numericCast(size) // <--- I also made the offset writable to simplify things
        }
    }

    return info
}

I doubt it's the proper way of doing it and I was just curious If the issue can be fixed. Anyway, is it possible to add support for Swift objects inherited from objective-c classes?