johnno1962 / injectionforxcode

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

Crash when `func injected()` is implemented #226

Closed olgagalchenko closed 7 years ago

olgagalchenko commented 7 years ago

I'm on Xcode 9, using Injection 9 version of the injection app. And injection works! I can see the changes when I dismiss the view controller and present again.

I'm running into a problem when I try to make the view controller re-load the view on injection. Like so:

extension UIViewController {
    @objc func injected() {
          viewDidLoad()
    }
}

But as soon as I implement injected(), it crashes when I try to inject. EXC_BAD_ACCESS in swift::_swift_getClass:

I talked to @rnorback, and he said that this happened to him when he implemented func injected() twice. And now I wonder if this warning is related to the crash: Class _[name] is implemented in both [app directory] and [InjectionBundle directory]. One of the two will be used. Which one is undefined.

Any ideas?

polac24 commented 7 years ago

Class ... is implemented in both... is the expected output on a console and does not mean anything dangerous.

olgagalchenko commented 7 years ago

Forgot to mention: I read about INJECTION_BUNDLE_NOTIFICATION in the FAQ, and registering for that notification is a good workaround.

Just add this somewhere in your view controller setup: NotificationCenter.default.addObserver(self, selector: #selector(self.viewDidLoad), name: NSNotification.Name(rawValue: "INJECTION_BUNDLE_NOTIFICATION"), object: nil)

It seems like implementing injected() is a better way to go, so I'm still working on it. giphy

johnno1962 commented 7 years ago

Olga, I’d need more information from the stack trace before I could tell you what the problem is. I suggest you try an injected method in the class you’re injecting then try it in a category on that class before you try an extension to UIViewController though I understand that works for some.

olgagalchenko commented 7 years ago

screen shot 2017-10-04 at 3 41 46 pm

olgagalchenko commented 7 years ago

Tried adding it to that one specific VC first.

func injected() {} crashes ✅ static func injected() {} is fine, but obviously I can't do self.viewDidLoad there

johnno1962 commented 7 years ago

Thanks for the stack trace - It helps a lot in concluding you’ll have to fall back to the “INJECTION_BUNDLE_NOTIFICATION” approach for your app alas. The implementation of instance level injected() is pretty complex and relies on being able to make a sweep of all objects in your application to find the ones which need to be messaged. There is a collection somewhere which isn’t compatible with this code: https://github.com/johnno1962/Xprobe/blob/master/XprobeSwift/XprobeSwift/XprobeSwift.swift#L165. If you want to help me debug exactly what the problem is we could TeamView but for now I’d stick to the notification if that works for you.

olgagalchenko commented 7 years ago

@johnno1962 you da best. Thanks!