Objective-C categories are extremely useful, but there are some problems with this power. These come in basically two forms which I know of:
Two categories attempting to add the same convenience method. In this case, it is undefined which one is used. If you are careful - not adding too many methods or using particularly common method names - the first problem should almost never be an issue.
New methods being added to a class by a writer that clash with a category. In this case the category overrides the class method. Since the class may not be under my control, I am more worried about this problem.
Backporting changes should be fairly safe, but implementing interfaces or adding convenience methods seem more dangerous. I know that Cocoa seems to use it for convenience methods quite a lot, but then again the base class is under there control. I think maybe they are just using the categories to reduce dependencies - so a String class can have convenience methods for working in Cocoa, but if you don't use Cocoa, it isn't pulled in.
So, how safe are categories/what guidelines are there for keeping them safe?
Usually, when extending code not under your control (e.g. Foundation), it's traditional to use a prefix or suffix on the method name to avoid these sorts of collisions.
Example from Peter Hosey's perform on main thread category:
#interface NSObject (PRHPerformOnMainThread)
- (id) performOnMainThread_PRH;
#end
It's not the most beautiful solution, but if you're worried about fragility it's a good idea.
I found the Google Objective-C Style Guide useful and it includes a convention to help avoid the collisions you mention.
Related
How can I share code between classes in Objective-C, the way Traits in PHP work?
I thought of using categories, but I wondered if there is something more suitable when it wouldn't be sensible to use inheritance.
There are several ways to share code between classes and each one has its own importance, depending upon the situation:
You can use inheritance.
You can declare Global Methods.
You can put the sharable code in AppDelegate.
You can use Singleton Class and put the common code in that class. (Not preferred for sharing code but we can still do it.)
All methods have their own pros/cons. You need to study their applications and use. Hope it helps.
Depends. You should ask yourself why do you want to have the same behaviour in various classes. You can use: Inheritance or design patterns (e.g. Composite pattern).
See:
Does Objective-C support traits/mixins?
Not sure if this is the best practice, or what you mean by "sharing code" but I usually have a static class which can hold global values.
The class is static and you can access it from anywhere like this:
[dataModel getMyValue];
[dataModel setMyValue];
It only becomes an issues if you try to write to it from multiple threads, but other than that its a good way to store shared data in your app.
Sharing code in Objective-C can be done only via subclassing or doing composition.
There is no equivalent of PHP's traits here. Categories work in a little bit different way. They're are assigned to a certain class, so you can't use code from category in any class. Unless you create NSObject category, which is good idea only in rare cases. You can treat category as a class extension.
It's possible 'share' interfaces having many different protocols. But it's not exactly what you need, I guess.
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.
In terms of good Objective-C coding practices, if I create a function that has no state, is it better to write it as a static method of some class or as a C function?
For example, I have a special filepath retrieval method that checks the Caches directory before proceeding to the main NSBundle. I currently have it as a static method under an otherwise empty Utils class. Should this be a C function instead?
The reason I've chosen to use a static method (for now) is that a) it's consistent with Objective-C syntax, and b) the class helps to categorize the method. However, I feel like I'm cheating a little, since I could easily fill up my Util class with these stateless static methods and end up with an ugly "shell class", whose sole purpose would be to hold them.
What convention do you use? Is one "better" than the other, by some objective metric? Thank you!
If you can think of an existing class of which this might make a good method, you can inject your method into it by making an Objective-C category. This keeps your two reasons for using a static method while not polluting the class space with an extra class.
For example:
#interface NSString (MyStringCategories)
- (NSString*) myCoolMethod;
#end
// [StringCategories.m]
#import "StringCategories.h"
#implementation NSString (MyStringCategories)
- (NSString*) myCoolMethod {
// do cool stuff here
return whateverYouLike;
}
#end
Now you can send myCoolMethod to any string. Cool!
In your particular case, it sounds like a method on NSBundle might be an appropriate architecture. And don't forget, it can be a class method, so you don't need to instantiate anything in order to call your method.
This is quite a difficult question to answer because for a lot of people the answer will depend on what their personal preferences and tastes are. I personally think that if you have a function that is a function, i.e. it has nothing to do with an object, it has no internal state etc. pp. please let it be a function and do not try to wrap everything you possibly can into an object just because you are using an OO language and you can.
In order to keep my answer short let me refer to a (imo) quite good book:
http://www.gotw.ca/publications/c++cs.htm
I know that this is for C++, but there are quite a few insights that can be shared with other languages (esp. Objective-C and Objective-C++) especially from the part called "Class Design and Inheritance". There you will find an item titeled "Prefer writing nonmember nonfriend functions".
Bottom line: "Nonmember nonfriend functions improve encapsulation by minimizing dependencies[...] They also break apart monolithic classes[...] [and] improve genericity[...]".
I think there is quite some truth in that item.
If there's no class to clearly bind it to, then I use a function. I also use functions for these utility bits because they can be stripped if not used or referenced. In that regard, it's also helpful to use a function because a link error is better than a runtime error (in the even the .m was accidentally omitted from the build, or if was referenced from another externally updated method). One problem with ObjC symbols is that they do not get stripped, so they naturally carry a high amount of dependency -- all the objc methods and classes, and required category methods must exist in the final binary. That's not an issue with really small programs or libraries, but it quickly gains weight with medium/large systems and libraries.
Everything does not need to be declared in an #interface - especially with larger systems where all those declarations will really turn your interdependencies into spaghetti. Compared to methods, functions are faster, smaller, may be optimized better by the compiler or during linking, and may be stripped if not referenced.
If you need polymorphism, it just belongs in a class for organization or convenience, then a class or instance method is often a better choice.
I also minimize declaring category methods for the same reasons. When you're using functions, you can easily write a wrapper method where you need it and get the best of both worlds.
I've recently discovered categories and was wondering when it might be appropriate to use them in a user defined class/new class. For example, I can see the benefits of adding a category to an existing class like NSString, but when creating a new class what would be the advantage of adding a category to this rather than just implementing a normal method?
Hope this makes sense.
Many thanks
Jules
The answer isn't really any different for your own classes than it is for framework classes. If you have multiple projects, you'll likely end up sharing some classes between them. However, you may want to extend some of your classes so that they work more easily with a specific project, but not want to include those extra methods in your other projects, where they might not make sense. You can use a category to extend your class without needing to subclass.
If I understand your question correctly, creating a "new class" is always "subclassing" because you're subclassing NSObject at the very least.
You could use categories on a new class to separate out sections of responsibility of a complex class. For example, all the basic functionality (instance variables, accessors, description, etc.) can go in one file (the "main" class file) while all methods to support a protocol (such as NSTableViewDataSource) can go in another.
Some take this approach to keep things "neat". I'm a firm believer in "if it's my own custom class, all its code should be in one file" so I do not personally do this. I demarcate different logical aspects of the class' code with "#pragma mark Some Section Name" to help navigation and readability. Your mileage may vary.
Adding a Category on NSString is useful when you want to call a method on every single NSString instance you will encounter. This is a real improvement over inheritance for this kind of object because they are used by the core framework and you don't have to convert a NSString object to your subclass when you want to call your custom method.
On the other hand, you can just put methods in, no instance variables.
In the book Refactoring by Martin Fowler, he has a section titled "Introduce Foreign Method" (A server class you are using needs an additional method, but you can't modify the class.) That's what categories are good for.
That said, there are times when using a category, instead of changing the class, is appropriate. A good example on using a category, even though you could change the server class, is how Apple handled the UIViewController MediaPlayer Additions. They could have put these two methods in UIViewController itself but since the only people who would ever use them are people who are using the Media Player framework, it made more sense to keep the methods there.
Is the concept of the Objective-C categories in anyway similar to the concept of mixins? If so: what are the similarities? In not: what are the differences?
To the best of my understanding:
Mixins
Syntactic sugar for composition
Added by the developer of the class, not the user
Can be reused by multiple classes
Can add instance variables
Can be implemented using forwarding in Objective-C
Categories
Similar to extension methods in other languages
Usually added by the user of the class, not the developer
Used by exactly one class and its subclasses
Can't add instance variables
To be clear the answer is NO - they are not the same.
The differences are outlined by John Calsbeek in the accepted answer, but I would say the key difference is the one where mixins can be used in different classes, whereas categories always extend exactly one class - which they declare in their definition.
This is the key difference because it means the use cases for these two features are utterly different. Another way of looking at it is that, if you're coming from Ruby to Objective-C and missing your mixins, you won't find any joy with categories.
The use case for mixins is that you have some code - methods and instance variables - that you want to reuse in several classes that don't have a common superclass. You can't do that with categories.
Mixins are effectively "multiple-inheritance" of the type you don't find in Objective-C. The closest thing in objective-c is protocols, just as the closest thing Java is interfaces, but they have neither instance variables nor method bodies (in objective-C or java). So you're generally left with creating helper classes or putting code in superclasses.
The use case for objective-c categories is that you want to add methods to an existing class - even a system or library class.
I would say that mixins are more powerful, but since it's an apples-to-oranges comparison, it would be pointless.
To be accurate:
the Ruby equivalent of Categories, is to simply reopen the class you want to extend and extend it. (You can do that anywhere in Ruby, and it's effectively identical to Categories)
I'm not sure what the objective-c equivalent to Mixins is though - anyone?
[Update] A bit more searching, and no there isn't an equivalent of Mixins in Objective-C, but the enterprising Vladimir Mitrovic has created a library that effectively does it. https://github.com/vl4dimir/ObjectiveMixin
I'm in two minds as to whether to use it or not: sometimes if the language you're using doesn't support something, it's easier to work with it rather than fight it or try to import your favourite features from other languages. ("If you can't be with the programming language you love, love the one you're with").
Then again, perhaps that's just a bit to snooty of me. The whole Aspect Oriented Programming movement has been glomming features onto Java for years (but never gaining much traction, I might add, outside of JBoss). Anyway, Vladimir gets extra kudos for using Ninja Turtles in his example.
On another side node: as a relative objective-c noob, it seems to me that categories are way overused in sample code I find all over the web. It seems common practice to add static helper methods to system classes with categories, when it would be just as easy to create a helper class to house those methods in your project, with less risk of them breaking when the system class is updated or you import someone else's library with their own such categories. A common example is adding new static color methods to UIColor. Why not just add them to a local class?
The one really good use I've seen for categories is adding methods, not to system classes, but to generated classes. So when you generate classes from your core-data object model, and you want to add new constructors or other methods that really do belong in the model class, you can do it with categories, allowing you to safely regenerate the model class if you change your model, without losing your work.
In summary:
- forget about categories as a solution for mixins
- categories are good for core-data but overused and overrated otherwise
Categories are defined for a particular class, as far as I know, you can't create a category and add the methods it implements to several classes.
With a mixin, you might derive a new class from your base and the mixin, then instantiate this new class to take advantage of it.
With a category, you are effectively adding directly the base class, so that all instances of that base have access to the functionality provided by the category.