johnno1962 / injectionforxcode

Runtime Code Injection for Objective-C & Swift
MIT License
6.55k stars 565 forks source link

Swift 3 fails on class properties #177

Closed FilipZawada closed 7 years ago

FilipZawada commented 7 years ago

Example:

Class MyViewController: UIViewController {
    var test = CustomClass()

    func injected() {
        print("injected")
    }
}

Results in EXC_BAD_ACCESS with a name var being "test" on following code:

// IvarAccess.h
const char *ivar_getTypeEncodingSwift3( Ivar ivar, Class aClass ) {
    struct _swift_class *swiftClass = isSwift( aClass );
    struct _swift_data3 *swiftData = (struct _swift_data3 *)swift3Relative( &swiftClass->swiftData );
    const char *nameptr = swift3Relative( &swiftData->ivarNames );
    const char *name = ivar_getName(ivar);
    int ivarIndex;

    for ( ivarIndex=0 ; ivarIndex < swiftData->fieldcount ; ivarIndex++ )
        if ( strcmp( name, nameptr ) == 0 )
            break;
        else
            nameptr += strlen(nameptr)+1;

    if ( ivarIndex >= swiftData->fieldcount )
        return NULL;
    // ...

A workaround is to declare CustomClass as @objc, but the downside is that the object must inherit NSObject.

Any ideas why is that and how to solve that?

johnno1962 commented 7 years ago

I’m afraid the instance level “injected” method is the least reliable part of injection particularly when Swift classes do not inherit from NSObject. I’ll take a look but I’d be reluctant to change the code at this stage.

FilipZawada commented 7 years ago

Thanks, works great with notifications

johnno1962 commented 7 years ago

Sounds good. I should have suggested that!