Back

Dynamic Code Injection for Good

This tool was developed long time ago, and the first post about it, wasn’t created by its author:) It’s a Dynamic Code Injection Tool or DYCI.

Prologue

There was a programmer too lazy to re-launch an application each time, so he has added some changes into its code.

I hope you know what Code Injection is. In general, these words are used when we’re talking about security holes, exploitation of some bugs in the code or about some other nasty things happened. But not today. Today we’ll discuss how to use code injection to accelerate the software development cycle. In short:
  • For one, this tool allows you to update code/resources of your iOS application without its restart.
  • Second, if you may wish to try it right way, just go to the DYCI github page and follow the instructions.

Story

The reason for this tool has been crafted in the first place is the laziness of the programmer, who was working on a rather big project. The programmer liked to write the code but it was annoying for him to wait while this big project was in the process of being compiled. But it wasn’t only about project compilation itself. In order to see changes the programmer introduced into the project, he had to go through a whole bunch of UIViewControllers, to press various buttons, to wait for  server responses and attend network operations. And for each change he made he needed to go through this path again. And again, and again…

Make changes. Wait until the project is compiled. Run the application. Go to the screen where you can see the desired result. Repeat the cycle until the desired result is achieved.

“There’s no problem with this flow”, – you may say. But, actually, there is one. And it’s a big one, as a matter of fact. In large projects, the amount of time you need to go from making changes to checking results can be really substantial.

The largest interval the programmer had ever experienced was about two and a half minutes. For one change only! But the funniest thing is that another programmer worked on the same  project was in this “change->compile->find->check” cycle for about two hours while trying to introduce a small change that would allow seeing the desired result. Each time when the programmer added a small fix he thought with no doubts that small change would be final. And each time he had failed. He had started to debug the program to understand what was going on. Then he realized that when he had tried to debug the program, its behavior had changed, and bug wasn’t appearing. So he had started to add logs and, finally, at the end of  the second hour, he found the bug and successfully fixed it.

The problem is that most of the programmers may end up in in this cycle for hours. It’s like a gambling. Each time you’re pretty sure that this time you will definitely win. But you’re continuing to fail again and again, wasting your and/or clients’ time and money. And then you get frustrated, start hating the project, work, testers because they found this bug; project manager for he’s saying that you’ve spent too much time on this small fix:), and so on.

Don’t allow this happen on your projects. Really. Time is a very precious substance. Your mood is of significant importance as well.

Why do I need to wait so long? I’ve changed only one line of code!

Solution

There are many things you can do in this very situation, and they are as follows:
  1. Write test (in general it’s much faster then trying to recheck everything manually).
  2. Update your application starting point to be able to jump right to the screen you need.
  3. Add logs for complex logic parts. Use a framework enabling to go on/off logs.
  4. …<Insert your solution>.
  5. Use DYCI :)

DYCI 

As already mentioned, DYCI is a tool that allows you to see changes that you’ve made almost immediately, right from Xcode or AppCode IDE.

Here’s a link to the video that shows how the DYCI tool can be used.

All you need to make this work in your project is to install it in your system, add DYCI to your project via Framework or CocoaPods, and that’s it. After these steps you’ll be able to insert code into your running project.

How it works

In short, when you’re pressing the hot-key, DYCI plugin recompiles the current file in the same way as it was compiled before, wraps the object file into dynamic library (Yes, I know you’re not allowed to do it in iOS), then the DYCI library in your app loads contents of the dynamic library into your app and performs a code update. There’s a more detailed description on the DYCI wiki.

After the code injection, DYCI library calls -(void)updateOnClassInjection method on each instance of injected class(es). This instances notification is the crucial part since the code you’ve changed needs to be run somehow. For example, if you’ve changed the method that is called each time when you’re pressing a button, then you can just press the button again. If you’ve changed the view WillAppear method, you can move back, and return to this controller afterwards. But in some complex cases you can add any code that will trigger the changes into -(void)updateOnClassInjection method. For example, if you’re playing with view layout, you can add this code:

That’s all. You don’t need to be in the “change->run->find->check” cycle. Now you can update it to the “change->inject->check” cycle. Profit. :)

Silver bullet?

Sad to say, but DYCI is not a silver bullet that can potentially solve all your problems. And there are some reasons for that:

  • Objective-C is a compiled language and it has some restrictions (static variables are hard to inject).
  • Programmers write hard-to-inject codes :) It is true. We are:) (Single tones are not supposed to be changed).
  • Life-cycle of objects sometimes doesn’t allow you to inject properly code (sometimes it’s hard to rewrite the object initialization phase).

But still, even with the limitations specified above, DYCI can accelerate the development process.

Possible usages

  • Add/change method of class.
  • Add logs to the class.
  • Update layout/screens.
  • Run small test code (Whatever comes into your mind).
  • Debug current object state (Sometimes debugger sucks).
  • Update strings in Localized.strings file.

Epilogue

Think about this tool as of yet-another-tool in a developer’s Swiss knife. As for me, I always add it to my project and use it when it’s really needed. :)

Cheers.

March 14, 2014
  • I don’t do this injection. My compiler compiles 50,000 lines in a second. My operating system is 130,000 lines total. I compile half ahead of time and half at boot time.

    • It’s not all compilation. In some systems “deployment” and the “find” step mentioned in the article can also take a lot of time.

  • Binoj

    Hi,
    I had tried to install DYCI and it showed as success. But When I’m trying to use it, it shows some error.

    Couldn’t load index file ‘/Users/Binoj/.dyci/index/59b71d5b4fd566e51dc49588769da933’ (/Users/Binoj/Documents/MyProjects/Calculator/Calculator/ViewController.m). Use default compilation instead

    I tried to reinstall but uninstall is not working. All my colleagues say’s its fake but anyway I tried. Please reply if you can help.

    • Paul Taykalo

      Hi #Binoj :)
      No it’s not a fake.
      Try to clean your project first.
      Then make sure, yo’ve installed dyci. I think you did :)
      Then make sure you’re trying to do this on Simulator.

      It works :)

      Also try. to check this link https://github.com/DyCI/dyci-main/wiki/FAQ. And if it will not work after this – you can contact with me – my Skype is on my Github page :)

      • BInoj VJ

        Thanks for all the Support. Never expected this much support from the author. Paul took 2-3 hours of his time to sort out my problem. Everything works now. DYCI saves a large amount of time in development.

        Thank You Paul. All the best for your future works. :)

Development