ObjC: Subclass a class whose #interface is inside a .m file - objective-c

I am trying to subclass a class whose #interface and #implemetation are buried inside of another class' ".m" file in order to restyle some of the views declared within. The superclass is a cocoapod, which I am unable to modify without forking the repo, which I am really trying to avoid doing. Is there any clever/hacky way to pull this off, or is it simply impossible?

In all honesty, I fail to see why forking would be a bad idea or why you would want to avoid it. That's the entire point of forking, modifying the code to fit your need more and perhaps later merge it back if the community finds it useful as well.
You can try to hack around this by redeclaring the class or whatever, but that implementation would be far more fragile than you having a fork which you have full control over (including merging any upstream changes). I think this is more related to a mental block of thinking that a fork becomes "your" code and "your" responsibility, while in reality it is just as much to maintain as it would be to keep the hacky version working across changes to the 3rd party code.

Related

Get Coco Class files programmatically

Using the objc/runtime.h we can create classes at runtime. How to export the .h and .m files from that class which is created at runtime?
Creating a .h is conceptually possible, but you'd need to write the code yourself to do it (using ObjC runtime calls to inspect the class and then write the file by hand). I don't know of anyone who has written this code already, but writing it would likely be an excellent introduction to the ObjC runtime functions. Note that the .h probably wouldn't be very friendly. For example, all object types in method signatures will be id. So it's kind of useable, but I can't think of a lot of ways I'd want to.
Creating a .m here doesn't make a lot of sense. The implementation of a runtime-generated class is going to be a bunch of IMP pointers to existing functions (which are themselves already compiled code). I don't know what you'd expect to be in the .m. In principle you could scan the executable to work out the names of the functions, and then write out a .m that looked something like:
- (void)someMethod {
SomeMethod_IMP()
}
This would probably get pretty complicated, and I can imagine several corner cases that would bite you in the general case.
This generally isn't how dynamically-generated classes are used, though, in the fairly rare cases that they are used. They're ubiquitous in KVO (but you'd never want a .h from that), and other uses of them are kind of similar: they usually are some magical subclass of an existing interface, so you never interact with them directly (and they almost always have an identical API to their superclass). What problem are you really trying to solve?
To get the implementation, you'd have to find or write a tool to translate assembly back in to Objective-C.
For just generating a header (interface), there are tools available. Use Google.
You cannot just tell the Objective-C runtime to create a new class from the .h and .m files because it takes a compiler. You need to hard-code the creation inside your project.
Create a subclass with objc_allocateClassPair
Add methods with class_addMethod (and properties with class_addProperty...)
Then you can use the new class.

Does a subclass go in a separate file?

I know that this may be personal preference but generally there are normal programming practices. So I am wondering if I created a class and a subclass would they go in separate files or the same one? I am talking in relation to objective-c but also in general.
Thanks.
The main reason to have classes in separate files is to enforce separation of concerns. By making it impossible to accidentally use private implementation details, you make it much easier to make statements like "only this class knows about this code/data, therefore I can change it freely as long as I make sure the interface to this class still behaves the same way".
The boundaries of your files then match the boundaries of what you have to keep in your head at any given moment, and the #import'ed #interfaces form the connections between the isolated areas.
You don't HAVE to, but generally speaking, yes. Keeping a subclass in the same file would be the exception to the rule.
First of all, you shouldn't just pile tons of code into a single file. Keep things simple so they're easier to understand when you look back at them later or when someone else has to look through your code to maintain it.
But if the two classes are so simple that you think you can fit all the code into one file and it still be simple enough to understand, then are you sure you need to subclass the original class? Why are you subclassing instead of just expanding the original class?
Moreover, what if you decide later that you want to add more subclasses. For example, a file with a Vehicle class may be extremely barebones. Then you subclass that and create Car class and figure it's still pretty simple, so I'll just keep it in the same file. But what happens when you decide to add more subclasses to Vehicle, like Plane and Boat. A file with Vehicle, Car, Plane, and Boat is definitely not the right approach. And a set up that has Vehicle and its subclass Car in the same file, but Vehicle's other subclasses, Plane and Boat are in their own files? Now this is confusing.

Objective-C subclassing and future compatibility

Objective-C supports subclassing and categories which allow you to add methods to an existing class. Here's my case.
// Made at earlier than iOS 5.x
#interface MyVC : UIViewController
- (void)childViewControllers;
#end
There was not the childViewControllers method before iOS 5.0. I could add the method without any concern. But now the UIViewController has a method with the name. If I build the legacy code written for iOS 4.x, the method will be overridden and it would make unpredictable result.
Is there any technique to defense my code from this kind of problems? This can be happen on categories or (maybe) something else.
One option is to add a prefix to all of your method names. Do this anytime you extend a standard framework class.
This same technique is used for class names to avoid possible collision in the future since there is no namespace like in Java.
Here's another thought to consider. How often does this happen? You need to weigh the effort of having to deal with the rare name collision by going back and renaming your method and updating affected code versus having to come up with a prefix naming scheme and typing those extra characters over and over every day.
Eternal vigilance against naming conflicts is necessary when dealing with late-binding systems such as Obj-C.
Unfortunately this means that you're always at risk for this kind of problem. In this case you did nothing wrong back in the 4.x days. All you did was write a good name for a good idea! But Apple likes that name too, and their stuff will take precedence every time. Your best bet is to add a prefix to your class and method names, especially when extending Apple's stuff.
In this case, just rename your method. The good news is that, in the mobile world, you don't need to patch old app versions while maintaining new app versions. It's only legal to have a single version of your app on the market at any time. What this means is that you can make a permanent change to your code base without having to worry about keeping the change in effect to v5.1.6 of your app, but not for v6.0.2. When a user updates, they always update to the latest version.
You will build experience the hard way (you're doing it now), as I did when I had a very important method called description.

Subclassing UIView vs UIScrollView

Ok, this might not be possible, but I've got a class (called CompositeView) that's a subclasses UIView. It uses some core graphics work to produce a custom background based on some options. Not a huge class, but bound to grow as my demands change/increase/whatever. The problem I'm having is I use this class a lot, in a lot of different places. But in a few of the places I need it to be a subclass of UIScrollView instead of a UIView. Interestingly enough, I can simply change the superclass and it all works perfectly fine. But not only do I not want all my other views to be a UIScrollView, it also interferes with the operation of some of them. So I need a class that's sometimes a subclass of UIScrollView and sometimes a subclass of UIView.
For now, I've literally copied all of the interface/implementation of the CompositeView, changed the class name to CompositeScrollView, and changed it's inheritance to UIScrollView. It works fine, but now I've got two sets of code that do exactly the same thing, just inherited from different parent classes. This makes keeping them both up to date a pain.
Is there a better way to do this?
Single inheritance languages force you to use delegation. You'd factor out the added functionality into a separate class that you instantiate for your derived classes and then write forwarding shims from the derived class to the instances. It's painful.
Objective C has protocols which would describe the added functions (any shims that are not overrides) and then the compiler would error-out if you didn't write the shim ... which you still have to do manually.
Objective C also has categories that allow you to extend existing classes but these can't be shared (you have to extend each class individually) so it doesn't really help.
The best thing to do is impossible, of course: have a UIScrollView inherit from YOUR UIView subclass.
#smparkes' answer is good, but sometimes delegation does not do what you want, or it's too inconvenient. In this case, it's probably the latter.
Consider using the thing as a UIScrollView everywhere, but breaking the functionality that you don't need. UIScrollView instances act exactly like UIView instances -- well, they ARE UIView instances -- so you might just resolve this simple problem, "interferes with the operation of some of them" and go on your way. Shut off zoom, shut off scrolling, etc...
Unfortunately, this is the reality of single inheritance languages. Whatever you do, do not try to solve this with anything like changing the isa. Should you ever have any success, it will not be lasting. Objective-C is only slightly dynamic and does not allow for this kind of thing to be used seriously by regular programmers.
Ok, maybe this is totally crazy, but is ISA switching an option?
object->isa = [SomeClass class];
See: Objective-C: How to change the class of an object at runtime?
If you implemented a UIView-subclass that knew how to switch its ISA pointer to the UIScrollView-subclass, you would only have to deal with one class and could even decide dynamically which of the views you want at runtime.
Please note, that this is purely theoretical. I have never used ISA switching in live code and I personally don't think it makes for a good design :P
EDIT:
But again, it isn't reducing any redundancies ...
I've read a bit more into the topic and it really doesn't seem to be recommendable (memory structure of old object stays unchanged e.g.)
Yes, you may be interested in using Class-cluster. This can produce objects let's say MyCompositeClass which will produce either MyCompositeScrollClass objects or MyCompositeViewClass objects.
Apple uses class cluster a lot for instance in NSArray, when you use it, behind the scene your manipulating different objects. The difference is based on the size of the array, for instance for some small arrays NSArray will instanciate a class that is specialized in small data structure, etc...
This has the advantage of having nice performance and the complexity is totally hidded from the user by this concept of class cluster.
I invite you to read some documentation about that, it might be more understandable.
https://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/ClassCluster.html
Hope this was helpful :)

Choosing a Singleton or a Category?

Fairly early on in my app, when I was a lot less experienced than I am now, I wanted to spice up some transitions between view controllers with my own custom animations. Having no idea where to start, I looked around SO for a pattern like MVC that could be accessed from nearly any controller at any time, and as it turns out, a singleton was the way to go.
What I didn't realize is that there seems to be a strong and well-defended hatred of the singleton pattern, and I myself am starting to see why, but that is beside the point.
So, a while later, I decided to move my very same implementation into a category on UINavigationController (after all, it handles transitions!), kept the original classes around for comparison, and am wondering which method would work best. Having thoroughly tested both implementations, I can say without a doubt that they are equal in every way, including speed, accuracy, smoothness, frame-rate, memory usage, etc. so which one is 'better' in the sense of overall maintainability?
EDIT: after reading the well-written arguments you all have made, I have decided to use a singleton. #JustinXXVII has made the most convincing argument (IMHO), although I consider every answer here equally worthy of merit. Thank you all for your opinions, I have upvoted all answers in the question.
I believe the best option is use the category.
Because if you are already using UINavigationController, do not make sense create a new class that will only manage the transition, like you told: (after all, it handles transitions!)
This will be a better option to maintain your code, and you will be sure that the thing do what they expect to do, and if you already have an instance that do the transitions, why create another?
The design patterns, like singleton, factory, and others, need to be used with responsibility. In your case, I do not see why use a singleton, you use it only to no instantiate new objects, you do not really need to have only one instance of it, but you do it because you want only one.
I'll make the case for a singleton object. Singletons are used all over UIKit and iOS. One thing you can't do with categories is add instance variables. There are two things about this:
MVC workflows don't tolerate objects with intimate knowledge of other objects
Sometimes you just need a place to reference an object that doesn't really belong anywhere else
These things go against each other, but the added ability to be able to keep an instance variable that doesn't really have an "owner" is why I favor the singleton.
I usually have one singleton class in all of my XCode projects, which is used to store "global" objects and do mundane things that I don't want to burden my AppDelegate with.
An example would be serializing/archiving objects and unarchiving/restoring. I have to use the same method throughout several classes, I don't want to extend UIViewController with some serializing method to write and read arbitrary files. Maybe it's just my personal preference.
I also might need a quick way to lookup information in NSUserDefaults but not want to always be writing [[NSUserDefaults standardUserDefaults]stringForKey:#"blah"], so I will just declare a method in my singleton that takes a string argument.
Until now i've not really thought too much about using a category for these things. One thing is sure though, I'd rather not be instantiating a new object a hundred times to do the same task when I can have just one living object that sticks around and will take care of stuff for me. (Without burdening the AppDelegate)
I think that the real question is in "design" (as you said, both codes work fine), and by writing down your problem in simple sentences, you will find your answer :
singleton's purpose is to have only one instance of a class running in your app. So you can share things between objects. (one available to many objects)
category purpose is to extend the methods available to a class. (available to one class of objects only ! ok...objects from subclasses too)
what you really want is to make a new transition available to UINavigationController class. UINavigationController, which has already some method available to change view (present modal views, addsubviews, etc.) is built to manage views with transitions (you said it yourself, it handles transitions), all you want to do is adding another way of handling transitions for your navigation controllers thus you would preferably use a category.
My opinion is that what you want to achieve is covered by the category and by doing this you ensure that the only objects which are accessing this method are entitled to use it. With the singleton pattern, any object of any class could call your singleton and its methods (and... it could work nobody knowing how for an OS version n but your app could be broken in n+1 version).
In this implementation, for which there is no need to use a Singleton, there may be no difference at all. That doesn't mean that there isn't one.
A plastic bucket holds as much water as a metal bucket does, and it does it just as well. In that aspect there seems to be no difference between the two. However, if you try to transport something extremely hot, the plastic bucket might not do the job so well..
What I'm trying to say is, they both serve their purposes but in your case there seemed to be no difference because the task was too generic. You wanted a method that was available from multiple classes, and both solutions can do that.
In your case, however, it might be a whole of a lot simpler to use a Category. The implementation is easier and you (possibly) need less code.
But if you were to create a data manager that holds an array of objects that you ONLY want available at one place, a Category will not be up to the task. That's a typical Singleton task.
Singeltons are single-instance objects (and if made static, available from nearly everywhere). Categories are extensions to your existing classes and limited to the class it extends.
To answer your question; choose a Category.
*A subclass might also work, but has its own pros and cons
Why don't you simply create a base UIViewController subclass and extend all of your view controllers from this object? A category doesn't make sense for this purpose.
Singletons, as the name suggests, has to be used when there is a need to be exactly one object in your application. The pattern for the accessor method ensures only this requirement being a class method:
+ (MyClass*) sharedInstance
{
static MyClass *instance = nil;
if (instance == nil) instance = [[MyClass alloc] init];
return instance;
}
If implemented well, the class also ensures that its constructor is private thus nobody else can instantiate the class but the accessor method: this ensures that at any time at most one instance of the class exists. The best example of such class is UIApplication since at any time there might be only one object of this class.
The point here is that this is the only requirement towards singleton. The role of the accessor method is to ensure that there is only one instance, and not that it would provide access to that instance from everywhere. It is only a side effect of the pattern that, the accessor method being static, everybody can access this single object without having a reference (pointer) to it a priori. Unfortunately this fact is widely abused by Objective C programmers and this leads to messed up design and the hatred towards singleton pattern you mentioned. But all in all it is not the fault the singleton patter but the misuse of their accessor method.
Now turning back to your question: if you don't need static / global variables in your custom transition code (I guess you don't) then the answer is definitely go for categories. In C++ you would subclass from some parent BaseTransition class and implement your actual drawing methods. Objective C has categories (that in my opinion is another way that easily messes up the design, but they are much more convenient) where you can add custom functionality even accessing the variables of your host class. Use them whenever you can redeem singletons with them and don't use singletons when the main requirement towards your class is not that it would be only one instance of it.