One of my core data subclasses has an NSSet of items. It is often (but not always, so no NSOrderedSet) useful to instead retrieve an ordered NSArray, so I added orderedItems to the class, which sorts them.
I then ran into performance issues so decided to try caching the orderedItems. My plan is to use an iVar, _cachedOrderedItems in the class, which I will return if it is not null.
The snag comes with my use of categories. I read some good advice about putting all of my custom code in a category so that I can re-generate the core data class if necessary and not lose all my customizations. One of those customizations is the orderedItems method.
It seems I can not declare an iVar in the category itself. And if I try to put it in the core data class instead, I can not access it in the category.
Do I need to move my custom code back into the core data class? Or am I missing something?
I have also heard about Mogenerator, and would consider learning to use this if it would help.
You can use associative references to add ivars to a class any time you can't modify the original class, including in categories. For a detailed example, see Faking instance variables in Objective-C categories with Associative References.
You own the class, so you can use a class continuation (discussed here) instead of a category. This allows you to add instance variables.
You should definitely use mogenerator. See for example http://importantshock.wordpress.com/2006/12/19/mogenerator-or-how-i-nearly-abandoned-core-data/.
You can make an Aggregate target in XCode, add a Run Script with the following:
mogenerator -m path/to/your/datamodel.xcdatamodeld/version.xcdatamodel --template-var arc=true -M /CoreData/Generated -H /CoreData
For every NSManagedObject you get a class and a subclass. When updating your datamodel, run the script again and the base class will be updated, preserving all the changes you made to the managed object subclass. Remove --template-var arc=true for none arc.
Related
I'm trying to use ILGeoNames classes in my project. But I have problem with understanding in which way I can use this classes for my purpose. There is "simple project" in this framework. From it I want only one thing: country time zone (I already have county name). Because there are many method, variables and others staffs I can't understand what exactly I need to use. Please, help me solve this question.
If its a bunch of classes and you want to make use of a certain class's methods or properties, then you have to #import name_of_class_you_want_to_utilize; at the start of your file and then make your calls. Class methods can be called directly, whereas instance methods require you to create an instance of the class to access them.
Since Objective-C does not support multiple inheritance, is there some other mechanism to share code between classes?
I'm writing a Cocoa library on top of an existing xml schema. Many elements in the schema (for example, ) are used in multiple types. I was hoping to centralize this somehow, so that I didn't have to add #property NSString *name and the associated code to generate the xml for the name property in every single class that has a name attribute. That would be fairly straightforward if multiple inheritance were supported, but I don't know how to do it otherwise.
The best thing I can think of is to create a common superclass that has a superset of methods to encode each optional property, then call the appropriate methods (i.e. encodeName) in the encoding method for each class. Does that seem like the best way to go?
I would recommend you create a new Category with your properties/functions etc and add said category to NSObject. That would make all properties and functions available to all subclasses of NSObject. It's not exactly multiple inheritance but provides a great amount of flexibility.
It is actually possible to add data to a class at run time using the runtime's Associative Reference functions. It's a little deeper than normal SDK work, but works quite well. It's not the same as a full property with getters and setters, but it does associate objects with an instance.
If the methods are only required on certain objects then maybe a sub class from that class is the way to go or a category on that specific class would be better. The category on NSObject is quite a wide net to cast.
If you want to add additional state then sub classing is probably your safest bet.
If you do add a category make sure you prefix your methods with something unique so to avoid any conflicts. E.g. PSMySpecialMethod as opposed to mySpecialMethod
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.
Can some one explain to me the difference between categories and inheritance in Objective C? I've read the entry in Wikipedia and the discussion on categories there doesn't look any different to that of inheritance. I also looked at the discussion on the topic in the book "Open iPhone Development" and I still don't get it.
Sometimes, inheritance just seems like more trouble than it is worth. It is correctly used when you want to add something to an existing class that is a change in the behaviour of that class.
With a Category, you just want the existing object to do a little more. As already given, if you just want to have a string class that handles compression, you don't need to subclass the string class, you just create a category that handles the compression. That way, you don't need to change the type of the string classes that you already use.
The clue is in the restriction that categories only add methods, you can't add variables to a class using categories. If the class needs more properties, then it has to be subclassed.(edit: you can use associative storage, I believe).
Categories are a nice way to add functionality while at the same time conforming to an object oriented principle to prefer composition over inheritance.
Edit January 2012
Things have changed now. With the current LLVM compiler, and the modern, 64-bit runtime, you can add iVars and properties to class extensions (not categories). This lets you keep private iVars out of the public interface. But, if you declare properties for the iVars, they can still be accessed / changed via KVC, because there is still no such thing as a private method in Objective-C.
Categories allow you to add methods to existing classes. So rather than subclass NSData to add your funky new encryption methods, you can add them directly to the NSData class. Every NSData object in your app now has access to those methods.
To see how useful this can be, look at: CocoaDev
One of favorite illustrations of Objective-c categories in action is NSString. NSString is defined in the Foundation framework, which has no notion of views or windows. However, if you use an NSString in a Cocoa application you'll notice it responds to messages like – drawInRect:withAttributes:.
AppKit defines a category for NSString that provides additional drawing methods. The category allows new methods to be added to an existing class, so we're still just dealing with NSStrings. If AppKit instead implemented drawing by subclassing we'd have to deal with 'AppKitStrings' or 'NSSDrawableStrings' or something like that.
Categories let you add application or domain specific methods to existing classes. It can be quite powerful and convenient.
If you as a programmer are given a complete set of source code for a code library or application, you can go nuts and change whatever you need to achieve your programming goal with that code.
Unfortunately, this is not always the case or even desirable. A lot of times you are given a binary library/object kit and a set of headers to make do with.
Then a new functionality is needed for a class so you could do a couple of things:
create a new class whole instead of a stock class -- replicating all its functions and members then rewrite all the code to use the new class.
create a new wrapper class that contains the stock class as a member (compositing) and rewrite the codebase to utilize the new class.
binary patches of the library to change the code (good luck)
force the compiler to see your new class as the old one and hope it does not depend on a certain size or place in memory and specific entry points.
subclass specialization -- create subclasses to add functionality and modify driver code to use the subclass instead -- theoretically there should be few problems and if you need to add data members it is necessary, but the memory footprint will be different. You have the advantage of having both the new code and the old code available in the subclass and choosing which to use, the base class method or the overridden method.
modify the necessary objc class with a category definition containing methods to do what you want and/or override the old methods in the stock classes.
This can also fix errors in the library or customize methods for new hardware devices or whatever. It is not a panacea, but it allows for class method adding without recompiling the class/library that is unchanged. The original class is the same in code, memory size, and entry points, so legacy apps don't break. The compiler simply puts the new method(s) into the runtime as belonging to that class, and overrides methods with the same signature as in the original code.
an example:
You have a class Bing that outputs to a terminal, but not to a serial port, and now that is what you need. (for some reason). You have Bing.h and libBing.so, but not Bing.m in your kit.
The Bing class does all kinds of stuff internally, you don't even know all what, you just have the public api in the header.
You are smart, so you create a (SerialOutput) category for the Bing class.
[Bing_SerialOutput.m]
#interface Bing (SerialOutput) // a category
- (void)ToSerial: (SerialPort*) port ;
#end
#implementation Bing (SerialOutput)
- (void)ToSerial: (SerialPort*) port
{
... /// serial output code ///
}
#end
The compiler obliges to create an object that can be linked in with your app and the runtime now knows that Bing responds to #selector(ToSerial:) and you can use it as if the Bing class was built with that method. You cannot add data members only methods and this was not intended to create giant tumors of code attached to base classes but it does have its advantages over strictly typed languages.
I think some of these answers at least point to the idea that inheritance is a heavier way of adding functionality to an existing class, while categories are more lightweight.
Inheritance is used when you're creating a new class hierarchy (all the bells and whistles) and arguably brings alot of work when chosen as the method of adding functionality to existing classes.
As someone else here put it... If you are using inheritance to add a new method for example to NSString, you have to go and change the type you're using in any other code where you want to use this new method. If, however, you use categories, you can simply call the method on existing NSString types, without subclassing.
The same ends can be achieved with either, but categories seem to give us an option that is simpler and requires less maintenance (probably).
Anyone know if there are situations where categories are absolutely necessary?
A Category is like a mixin: a module in Ruby, or somewhat like an interface in Java. You can think of it as "naked methods". When you add a Category, you're adding methods to the class. The Wikipedia article has good stuff.
The best way to look at this difference is that:
1. inheritance : when want to turn it exactly in your way.
example : AsyncImageView to implement lazy loading. Which is done by inheriting UIView.
2. category : Just want to add a extra flavor to it.
example : We want to replace all spaces from a textfield's text
#interface UITextField(setText)
- (NSString *)replaceEscape;
#end
#implementation UITextField(setText)
- (NSString *)replaceEscape
{
self.text=[self.text stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceCharacterSet]];
return self.text;
}
#end
--- It will add a new property to textfield for you to escape all white spaces. Just like adding a new dimension to it without completely changing its way.
I'm new to objective-c and need to extend a standard class of a framework with an instance variable plus accessors. I heard that this is done with a so called "category", which sounds pretty confusing to me. How does this basically work?
A category adds methods to the table of methods inside a class. It's very handy for adding application specific methods to existing framework classes.
If you need to add instance variables to a class, a category won't do the job -- categories only add methods, not data. To add instance variables, you must subclass.
A category of a class adds methods to that class. It cannot add instance variables.
If you need to add instance variables you may want to subclass instead.