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

Seems to crash when trying to get the type of a UIViewController. #36

Open valleyman86 opened 5 years ago

valleyman86 commented 5 years ago

The following code will crash

class ViewController: UIViewController { }
let info = try? typeInfo(of: ViewController.self)

in RelativePointer->advanced() on let offsetCopy = self.offset

Any ideas what would cause this?

wickwirew commented 5 years ago

What version of swift?

valleyman86 commented 5 years ago

Swift 4.2

valleyman86 commented 5 years ago

Not sure if it is relevant but let info = try? typeInfo(of: UIViewController.self) will return nil. The error being "couldNotGetTypeInfo". I assume this is because "Runtime.Kind.objCClassWrapper" is not supported.

valleyman86 commented 5 years ago

Update: I was able to get objC classes to work by adding support for an ObjCWrapper. I am now able to createInstance on things like UIViewController and UIButtons.

As for this crash I think it is related to accessing typeDescriptor (Nominal Type Descriptor). From what I understand in swift 4.2 this is going away right? Anyways I didn't see Runtime doing much with mangledName so I commented that out (I dont need it for my use case anyways). I then set the properties for the class using ObjC runtime if the rodataPointer lowest bit is 0. According to the docs this will be 1 for swift classes and it seemed to reflect that in my testing.

Long story short I think I got this mostly working now. Maybe I can make a PR for this later but I was honestly unable to get SPM working and cocoapods was out of date so I just manually created a new framework for runtime.

valleyman86 commented 5 years ago

Seems after getting an object created and such I still cant set the values of a swift class that inherits from UIViewController. (Same code as above). No error it just doesn't do anything and the values remain whatever they were. I suspect this is an issue with a class that inherits from NSObject eventually cant have its values set the same way... not quite sure.

valleyman86 commented 5 years ago

Further research into this suggest it may because we need to account for the super class when dealing with the field offsets. I was able to detect that the first field is actually perfectly offset at the value returned by class_getInstanceSize of the superclass.

I found this code in the swift runtime (Metadata.h)

unsigned getFieldOffsetVectorOffset(const ClassMetadata *metadata) const {
    const auto *description = metadata->getDescription();

    if (description->hasResilientSuperclass())
      return metadata->Superclass->getSizeInWords() + FieldOffsetVectorOffset;

    return FieldOffsetVectorOffset;
  }

I guess the main challenge here is that these fields are only used for swift objects.

wildthink commented 4 years ago

@valleyman86 How did you fix the support for ObjCWrapper.? https://github.com/wickwirew/Runtime/issues/36#issuecomment-473648563 thanks.

NSExceptional commented 3 years ago

@wickwirew any update on this? I'm running into very simple issues when working with objects, wondering if this is related.

Edit: opened a new issue about this #81