Occationaly I see snippets of code creating new methods for objects and such that looks like this:
#implementation UIImage (Extras)
- (void)aMethod:(id)anObject {
// some functionality
}
#end
Where do I put this code? Do I put it in the class I'm currently writing code for? If so at what point in the code do I need to put this?
Thank you.
You can put this category code whereever you like. In general, this code should be in a file called UIImage+Extras.m and a matching header file UIImage+Extras.h.
This is an Objective-C feature known as a "category". See these articles for more info:
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/ObjectiveC/Articles/ocCategories.html
http://macdevelopertips.com/objective-c/objective-c-categories.html
For the sake of simplicity and to keep code clean I usually put class categories in separate files.
But in general I think you just need to declare your category in some header and import it to let compiler know about methods you add. Implementation of those methods can be put in any (implementation) file, but once again I think it is better to keep it in separate place.
Related
I had this problem with import statements with my own classes using forward declarations to fix that. I have a method that uses type CTFramesetterRef. So I needed to add the CoreText framework. If I declare the method in my .h file, do I just
#import <CoreText/CoreText.h>
in my .h file and not my .m file. Are there any hard and fast rules for this? Sometimes I see code that has it in the .m, sometimes in the .h. To me it seems like what I see is declare it in the .m if you can, if you have to put it in the .h, put it there instead, and if you can use a forward declaration for a class, then do that. Just not sure what the proper way to do things are. Thanks.
"declare it in the .m if you can, if you have to put it in the .h, put it there instead, and if you can use a forward declaration for a class, then do that." - I would say this is the proper way to do that.
I'm looking through the PageControl example from Apple. They have a class called ContentController. In a subclass of the class, PhoneContentController.m, they have this:
#interface ContentController (PrivateMethods)
- (void)loadScrollViewWithPage:(int)page;
- (void)scrollViewDidScroll:(UIScrollView *)sender;
#end
Is this adding a category to the class ContentController?
Why would they put it in this file, versus the original file they created?
By declaring it in the PhoneContentController.m file, does it give this class access without having any additional directives for the compiler?
(I'm trying to understand the OOAD principles and why Apple does certain things in their example code, hierarchies, etc). Thanks!
Is this adding a category to the class ContentController?
Yes, they are adding a category.
Why would they put it in this file, versus the original file they created?
If I recall correctly, this is done because there are two UIs, (one for iPad and one for iPhone,) so that they can write the code only once and use the same handlers in the different view controllers.
By declaring it in the PhoneContentController.m file, does it give this class access without having any additional directives for the compiler?
Well, yes. It's a small matter to compile an additional 4 line file, and I think this is a template related decision rather than a compiler related one. It's simpler to distribute, say, 3 sample files instead of 4, for example.
How i can obtain bar code type with zxing library? Delegate method return only barcode in text.
The delegate call back is,
- (void)decoder:(Decoder *)decoder didDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset withResult:(TwoDDecoderResult *)twoDResult {
The readers property in Decoder.mm is a list of FormatReaders.
#interface FormatReader : NSObject {
zxing::Reader *reader_;
}
The reader_ variable in FormatReader will be a C++ subclass of zxing::Reader, like QRCodeReader. Checking this class name will help identify what symbology you're getting. Beware some of them are 'MultiFormat' readers that combine other readers, so you might have to do some clever inspection.
See How to get class name? for how to get class name in C++.
If you end up making helpful modifications, make sure to submit a patch back to zxing. Good luck!
So the other day I was sick of typing out repetetive addTarget:action:forControlEvents:s, and macros are only entertaining for so long, so I did this:
#implementation UIControl (xx)
-(void)addTarget:(id)target action:(SEL)action
{
[self addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
}
#end
and simply added it at the top of the .m file in question.
Works great of course, but notice the "xx".
What's the best thing to NAME a "nameless" Category like this?
Note that it really NEEDS NO NAME as the name will never be used ANYWHERE. The best thing would be to give it no name - but syntactically you cannot leave that blank.
(If you leave the xx blank - it becomes an "Extension" which is quite different.)
I was thinking maybe:
a single underscore
the name of the class again identically
"quick"
perhaps the name of the class in this file (as in "quick extra routines for UIControl in CherryBomb") - so it would be UIControl(CherryBomb), i.e., to remind you that these extra routines are handy for CherryBomb and are indeed in the file CherryBomb.m
"x"
your or your company's initials (use the same "quick" Category name everywhere)
"ThisTextNeverUsedAnywhere"
(By the way ... it appears you do not actually need to include an interface for such a Category, i.e. you can omit...
//you can actually get away without these lines...
//#import <UIKit/UIControl.h>
//#interface UIControl (x)
//-(void)addTarget:(id)target action:(SEL)action;
//#end
... that part and it works fine.)
For people who love Categories, and who doesn't, what's the answer to this troubling question?
What should you name a "nameless" Category where the name is never going to be used again and is irrelevant, because the text is typed directly only in the top of one .m file for use only in that file?
I just use Private. Because they are, well, private... I'd love to hear people's thoughts on that though. :)
An Extension is the same as a Category except the extra methods must go into the same implementation as the original class.
This is useful for adding private methods to a class that don't need to be exposed in the header file, or redeclaring #properties.
Obviously, this can't be used when adding Categories to classes that you don't have the source for. e.g.
UIControl
As for how I name Categories: I use my Three Letter Prefix and the word "Extensions" such as:
UIControl (ADNExtensions)
I like the naming convention "UIControl+MyClassName" for something like that, and naming categories that add to system classes generally as "UIControl+MyPurpose".
If it's a quick, off-the-cuff category, then I'll call it something like DDAdditions. If it's supposed to be a bit more formal, then I'll figure out what the defining purpose of the category is and construct a name off that.
edit more information:
Here's what I do:
When I name the file that contains the category, it is always of the form:
BaseClass+CategoryName.h/m
So if I have a UIButton category called FooBar, the name of the file is UIButton+FooBar.h/m. Seeing this construct in my source tree instantly tells me 2 (potentially 3) things:
That I'm extending a class
What class I'm extending
What the purpose of the extensions is (if the category name is descriptive enough)
If I'm declaring multiple categories in a single file, then the "BaseClass" bit can vary depending on how the extended classes are related.
If there's a mutable-immutable relation (ie, I'm extending both NSArray and NSMutableArray with a category that offers both immutable and mutable variants [ex: -[NSArray shuffledArray] and -[NSMutableArray shuffle]]), then I'll simply use NSArray as the base class.
If there's a kind relation (the things I'm extending are both collections), then I'll try and come up with a base name that reflects that relation, like Collections+CategoryName.h/m.
If I can't come up with a way that the categories are related, then they shouldn't be in the same file. Using a single file for "the categories that just add little things here and there with no defining purpose" is (in my opinion) wrong. File names, like method names, should reflect the purpose of the file.
Coming up with a proper category name takes practice. If I'm in a hurry or am just adding a category to try something out, I'll use "DDAdditions" (my initials + "Additions"). If I'm using a category to hide methods on a class, I'll go with something like "Private" or "Internal".
Otherwise, I find the purpose of these methods and construct a name out of that.
For example, if I'm adding a method to NSDictionary to take its key-value pairs and URL encode them as a query string, then I'll call the category DDURLAdditions or DDURLEncoding or something like that.
The over-arching principle here is to be descriptive. Really it doesn't matter what you call your category or what you name your file as long as its clear what they are. (One of the things we love about Objective-C is that its verbosity makes it largely self-documenting) The only other thing to watch out for is to make sure that your category doesn't have the same name as another category for that same class. (and also that your method names don't conflict, etc)
I can't see anything wrong with _.
The problem with categories is that the compiler and the linker NEED the name of the category to be able to differentiate your symbols or else it can't find the symbols and build your class properly. So call it "Private", or "Additions", or "Convenience" but in any case you'll need a name, and if you happen to have two categories of that type for the same class in different files I advise you to find different names, or better yet: Follow Dave's suggestion.
Note, the name could have been removed for class extension simply because they're only interfaces, it was easy to instruct the compiler to ignore the category name and simply add the methods to the main class block as temporary declaration and thus put a warning inside the #implementation when the methods aren't implemented.
Whereas for a category you needn't to have an #interface matching an #implementation or vice-versa: #interface would contain only declarations that you don't necessarily need to implement (however, don't try to call them if they aren't actually implemented you'll get a crash...). And if you put the #implementation alone without #interface before where you use, the compiler will have stored the method declarations and thus removed the "might not respond to selector" warning.
Note: you can also write an Xcode macro to build your "convenience" category directly...
I prefer categories to be named after what they do. In the example you gave, I would call it "UIControl+Convenience" or "UIControl+Targets". KWTargets or JBTargets is also fine. Most of your examples tell you little or nothing about what the category does, which is confusing when you try to understand unfamiliar code (either because someone else wrote it, or because you haven't looked at it in a while).
So, I read this post, and it's pretty much exactly what I was looking for. However... it doesn't work. I guess I'm not going to go with the singleton object, but rather making the array in either a Global.h file, or insert it into the _Prefix file.
Both times I do that though, I get the error:
Expected specifier-qualifier-list before 'static'
and it doesn't work. So... I'm not sure how to get it to work, I can remove extern and it works, but I feel like I need that to make it a constant.
The end goal is to have this Mutable Array be accessible from any object or any file in my project. Help would be appreciated!
This is the code for my Globals.h file:
#import <Foundation/Foundation.h>
static extern NSMutableArray * myGlobalArray;
I don't think I need anything in the implementation file. If I were to put that in the prefix file, the error was the same.
EDIT
So, I removed the .m file from Globals, and I just have the code about in Globals.h. Assuming I am going to continue with this terrible practice of having global variables (I know it's bad, I just want to test this out), I now have a new error. It says:
"Multiple storage classes in declaration specifiers"
If I remove "extern" it works and if I remove "static" it works, but having both doesn't... what now?
****Double Edit****
Aright, so I've tried adding the array to my UIApplication Delegate, but I'm doing it wrong because it isn't working. Could someone give me some example code as to where to place it an access it? I don't know if it should go in the implementation, or somewhere else, and once the array is initialized how to access it from the other files... Do I set a new variable to the array, or something?
Just a general programming suggestion--don't share an array. You have no control over it and it will be virtually impossible to trace if something changes it at a time and in a way you aren't expecting.
Instead, create an object with the array inside it and make that object a singleton (or better yet, make a factory for it).
Whenever you want to modify your array, call methods on the object to do so. If you do this, I bet you will find a lot of redundant code you can factor into this object (for instance, searching the array for a value--make a "search" method in the object instead and pass in a value).
It may seem like a lot of work you shouldn't have to do, but you'll find it's fairly fun work, and you should find that you DO have to do it once you see how much code belongs in this object...
Just add the array as a property of the application delegate, and access it like:
[[UIApplication sharedApplication] myArray];
The two (main) ways of making an array global are separate -- either you have a class with a method
static NSMutableArray *foo;
+(NSMutableArray *)foo {
return foo;
}
(in the .m file) with the static piece NOT in the header file, or just
static extern NSMutableArray * myGlobalArray;
with out the singleton wrapper (which I think is better as it saves you from having an extra bit of unnecessary code)
Either way, it is still a bad practice that I would try to avoid.
In general, the presence of a "Globals.h" file is a bad smell that there's an antipattern at work.
I would even advise against Bill K's advice and not use a Singleton pattern at all.
Instead, create the array in your app delegate, and pass it to your root view controller(s), and along the hierarchy to the components that need access to it.
This is what I was looking for:
http://derekneely.com/tag/app-delegate/
Thank you for pointing me in the right direction!
#import <Foundation/Foundation.h>
static extern NSMutableArray * myGlobalArray;
#interface Globals : NSObject {
}
#end