There are some very powerful features in the Objective-C runtime, so is this something we should be taking advantage of more?
During my time as a developer I have seen my fair share of examples where people have abused the Objective-C runtime to solve a problem, when there was most likely a better solution.
One common example of this was when a developer uses objc_setClass() to change the class of an instance at runtime. I’ve seen this happen when developers want to instantiate a controller from a storyboard, but then subclass that class and go thorough the same initialiser.
This is all very straight forward, but what happens if you now want to subclass this function?
This will still return an instance of HorseViewController. We could then override the super method, and return our own instance. However this would mean duplicating the controller in the storyboard for our subclass.
This is where I have seen the Objective-C runtime used incorrectly to solve the issue above.
So why is this bad?
To really understand this we need to know a little about how the Objective-C runtime works, and how swift objects are converted to run inside this environment.
In essence, every object once compiled down to the Objective-C runtime, is a struct, which contains a single pointer called an isa, which is of type Class. That’s it… There isn’t really much to it. All I can say is that every object in the objc runtime has one of these pointers.
So what is an isa pointer?
The isa pointer is the first pointer-sized piece of memory that is allocated when initialising an object, and it contains information about the objects class. We can see this by looking at what makes up a Class.
Again a class is just a structure, and just like an object, it also has an isa pointer, which tells us that Class, is in-fact also an object. We also have a number of Objc2 only attributes.
super_class – this is a pointer to the objects parent. This is what is returned when we call super on an object. Notice there is no pointer to retrieve the subclasses.
objc_ivar_list – this is the list of instance variables for the current class. Pretty self explanatory. Same with objc_protocol_list – which is again just a list of the protocols a class conforms to. As these are both pointers they can be both changed out at runtime.
objc_method_list – is slightly different to the two above, as it is a pointer to a pointer, which allows the objc runtime to modify the classes methods.
objc_cache – the object cache is very important, as it is this that tells the build system if there is a cached version of the class already stored. When the runtime searches for an implementation which matches a selector, it will first check the cache to see if a value exists, and if it doesn’t, it will query the rest of the hierarchy.
name, version and info are just some metadata set on the class.
instance_size – is the amount of memory that class needs to be allocated.
Now we know more about what happens behind the scenes we can finally look at why changing the class at runtime could be a problem.
All we are doing when we call object_setClass is changing the isa pointer to the one of our new class. Our original object has already been initialised, and the correct amount of memory has been allocated. When we change the pointer we now have a new class which may need more memory, if it has more methods, ivars etc. This is where the problem lies. New methods may not have enough memory to execute so we could start to see random crashes appearing.
In my option if you want to share UI from a storyboard or xib, then I think the best approach would be to split it up into separate views or child view controllers. These can then easily be re-used in multiple view controllers.
- Cheshire Half Marathon 2020 September 27, 2020With most of 2020 being a complete right off, it meant I could knuckle down and get plenty of good training in. Races should have been on the cards with Manchester marathon, Holkham triathlon and Valencia marathon being the main goals. However, like most events...
- Helvellyn September 13, 2020Hannah and I were due to get married on the 29th August and were supposed to be spending two weeks hiking around Canada. Then the coronavirus happened and all our plans went out the window. Instead of sitting home doing nothing, we decided to take...
- Uploading content, React, GraphQL, Rails and Active Storage April 26, 2020There are some great blog posts out there on all these topics but I found a lot to be out of date. The versions I’m using are below. Rails 6.0 React 16.3.1 Apollo 3.0.0 Rails To start off with we will set up our backend...
- Full-stack introduction using Rails, React, Docker and Heroku February 9, 2020Coming from mainly a mobile background, I’ve always been interested in learning new technologies that I wouldn’t use in my day to day field. I find it fascinating that especially with today’s technology it is easier for an individual to write an entire end to...
- Malaga Marathon 2019 December 21, 2019All the training these last few months had been leading up to one goal – to run a sub-3-hour marathon in the Malaga marathon. The training had been going great, and with a 1:22 in the Tatton Half, I felt like I had a great...
- Run Tatton Half Marathon 2019 November 9, 2019It’s been a while since my last run event, with the Chester half being back in May. With my marathon training now in full swing for Malaga, I was going to treat this as a fast training run. I had no real goal time in...
- Property Wrappers October 31, 2019First introduced in Swift 5.1, property wrappers allow us devs to add our own implementation details to a property before they are initialized. Currently, by delaying initialization we can declare a property as lazy, and then return our property when it’s first requested. Property wrappers...
- Shropshire Triathlon 2019 September 15, 2019A step up was on the cards for this race, as this would be my first shot at an Olympic distance triathlon after my sprint distance race that I did back in April. I did not have the best prep going into the race, as...
- Running Xcode Tests from CI August 3, 2019The ability to run a suite of tests is a great way to cut down on manual testing time, whilst still having the knowledge that any new changes have not broken the codebase. There are a number of different options when it comes to writing...
- Method Swizzling June 29, 2019When anyone mentions swizzling I automatically get worried. Method swizzling is an Objective C runtime feature which allows for the switching of method implementations. This means any function can theoretically be switch out for another one at run time. The Objective C runtime as a...