Going Beyond Syntax
Being one of a few mobile developers at thredUP, other engineers are often horrified looking at the supposedly “bloated and wordy” syntax that make up Objective-C and Cocoa (Touch). Yes, our method declarations are long and there are a scary amount of @ symbols, but inside lies a powerful beast. So for those naysayers and anyone who wonders about iOS development, here are a few of my favorite things about working with it.
1.) The Objective-C Runtime
After developing for iOS over the past five years, I still only venture into the runtime code when I know I really need to. But to this day, my mind continues to be blown by the power and flexibility it gives to us developers. Whether you’re dealing with your own, third party, or native Apple code, the number of shockingly cool things you can do using the Objective-C runtime environment is endless. There is far too much to touch on in just this post, so for now I’ll mention an experience of mine using third party libraries.
We recently had a third party library in our code, which I will leave unnamed. But essentially this third party library would fire off a bunch of work on the main thread, when in fact it should have been (and eventually was updated to be) done on a background thread. For those unfamiliar with the environment, the main thread is typically reserved for things that are needed to update the user interface. If you ever see a laggy interface, or perhaps even frozen, this is due to something blocking the main thread. In our case, using the Objective-C runtime enabled us to to intercept their method call, and wrap it it onto a background thread.
With just this small amount of code, we’re able to exchange method implementations at runtime so whenever the third party library method is called, the body of our method is run instead. We then move the call onto a background thread and fire the original third party method (And yes I know it looks very odd, but that is actually calling the third party method). Wondering how you can know what method declarations look like inside private libraries? That’s just another beautiful function granted by the runtime libraries. You can print them all out!
2.) Key-Value Observing
This would have to be the most contentious API I can think of. Some developers love it, and others hate it. I will admit, I was originally on the opposite side of the fence, but that quickly changed. In the thredUP application, users can add and remove items from their cart from numerous locations. Wouldn’t it be nice just to automatically know when the number of items in someone’s cart changes? Well KVO gives us this right out of the box.
Admittedly, any method that passes in four different parameters is a mouth full. This snippet however boils down everything you need. Developers commonly ignore the context parameter, and instead decide to just rely on the keyPath. Using a static variable however ensures we will have no false positives when using KVO inside classes that may have superclasses registering for equivalent keyPath updates. Some people may argue that you could achieve this same outcome using NSNotifications. I would agree with that for some use-cases. If however, you are wanting to be notified of changes in properties that you don’t have access to write to, KVO would be your best bet. Not to mention, you don’t even have to write additional code to force the KVO update to be fired. The same cannot be said for NSNotifications. And yes, obviously not everything is KVO compliant. If an instance variable is written outside its setter, these will not trigger KVO notifications. There is an upside to this though. If you are watching your own properties with KVO, there are certain times you don’t want to notify everyone of changes. Writing directly to an instance variable affords you this flexibility. There are many additional things to note in implementation details, but at a high level KVO affords you a lot of functionality with very little work required.
This is not a pattern limited to Objective-C, but it sure is wonderful to use with it. Apple even encourages the use of this pattern, demonstrating it in classes as fundamental as the UIApplication class. They are perfect for abstracting heavy lifting outside of your view classes, and sharing data between different areas of code without having to actually transfer that data. At thredUP, we use them to manage network transactions, map http response data, listen for state changes, and the list goes on and on. Singletons are great workhorses and incredibly easy to setup.
With this setup, our singleton will be lazily instantiated whenever we need it. These snippets show how little code it actually takes to setup a simple singleton, and one of the major benefits of using them. Exposing readonly variables and wrapper methods in singletons are handy for limiting the spread of bugs. It is much easier to trace issues when certain methods or variables can only be called/modified inside of the implementation itself. As you can see, the ’someStringVariable` is exposed to the public but only writeable inside the `SomeManager` class. Likewise, the `somePrivateNumber` variable is only visible inside the `SomeManager` class and is implicitly only writeable inside that same class. You can expose this readonly/readwrite logic in any type of class in Objective-C, but it is particularly useful for encapsulating unrelated data work from view components.
This list only scratches a high level surface. It may seem foreign at first, but once you go down the rabbit hole, things just get cooler and cooler. Feel free to contact me at firstname.lastname@example.org if you want to talk.