Hiding sensitive business logic in Objective-C
So you have some business logic in a class that you want to hide from the users of your class? Let’s say that you are working on a library project and you have to expose the header file of this particular class to your user but once you do that, it’s easier for dubious programmers to find the class name behind your business logic and potential reverse engineer your app.
In Objective-C, we can hide the implementation of our business logic by taking advantage of the Objective-C runtime. Here is our action plan:
- We will create our class called Person (the class whose header file is going to be exposed to evil programmers out in the wild!)
- We will create another class called PrivatePerson and will include our business logic in there
- We will then redirect requests from the Person class to the PrivatePerson class
And obviously we will not export the PrivatePerson’s header files for the programmers, are we crazy? No!
Ok so let’s begin by creating the interface for our Person class like so:
The properties are fine. But the method named fullName is going to have business logic in it. It will return the current first name and the last name, separated with a space. We don’t want the logic for this method to be inside the Person class so what can we do? We will go first and create the class named PrivatePerson and we will put our business logic for the fullName method in there. Let’s start with the header file. But before we do that, remember that the firstName and lastName properties are in the Person class. So how can the PrivatePerson class that contains the business logic calculate the full name without having those values? Well, we just have to pass those values to PrivatePerson as parameters like so:
Then we will implement the PrivatePerson class:
Now what we have to do in our Person class is to implement 2 methods. The first method is methodSignatureForSelector: and this method will be called on our Person class whenever the fullName method is called. Since Person doesn’t implement fullName, the runtime will, in the process of throwing an exception, first find out whether the Person class can handle this message. By implementing the aforementioned method, we get a chance to return a method signature that corresponds to the fullNameFromFirstName:lastName: method in the PrivatePerson class, like so:
Note: self.privatePerson is a private property of our class. Look at the next screen shot to learn how we implement that property’s getter.
Then we will implement the forwardInvocation: method using which we redirect the call for the fullName method into the fullNameFromFirstName:lastName: method in PrivatePerson class:
Perfect, in your app delegate for instance, test this out:
You can see the correct value of “Vandad Nahavandipoor” will be printed out to the screen.
That’s all good and fluffy and warm and nice. But LLVM will be nagging at the incomplete implementation of the fullName method in the Person class since we haven’t implemented it there. Remember? That was our goal! Doh!
So using the awesome techniques described by the lovely people behind LLVM, we will silent these incomplete-impelemntation warnings in our Person class like so:
Awesome, problem solved. Happy coding everyone! :-)