PageControl example code for the iPhone notation question - iphone

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.

Related

Objective-C: Is a class just a .m and .h file?

I'm still coming to terms with classes and objects in Objective-C.
Is a class simply the combination of an interface and implementation file? Or, to put it another way, when would you say to yourself "I need a new .m file for this". At the moment I make a new implementation file when I want to put certain methods and variables in a separate place so that my main code doesn't become massive.
Any help would be greatly appreciated.
Strictly by convention and not by necessity, every new class should have an interface file (.h file) and an implementation file (.m file).
As far as using new .m files for distributing your methods, this is fine.
While convention dictates a pair of .h and .m files per class, the former containing the #interface and the latter containing the #implementation, there is no such requirement and, in fact, many of the system provided classes are divided across several files both in interface and implementation.
Technically, you don't need an #interface at all.
The absolute minimal class definition is:
#implementation Foo
#end
In that the above defines a class Foo that is a new root class. However, the compiler will warn about this.
Effectively, the minimal class definition is:
#interface Foo:NSObject
#end
#implementation Foo
#end
Note that NSObject is intentional; if you are going to make a class that will be compatible with the system frameworks or, even, the system runtime, inheriting from NSObject is pretty much required.
Syntactically, it is up to you as to how you separate the #interface and the #implementation. Traditionally, the interface goes in a header file such that others might #import it and use it while the implementation goes into a compilation unit -- a .m file -- to be compiled and linked exactly once.
But that is convention, not requirement. I've often defined a class --- #interface + #implementation -- entirely in a single .m file solely for use within the #implementation of some other class; effectively, a private class.
Note that class extensions -- #interface Foo() -- were expressly created to allow you to declare additional properties and methods on a class outside of the .h file's #interface Foo:NSObject. It allows a class to effectively have hidden API or to create a property that is publicly readonly and privately read-write.
No it's not. You can place multiple classes in a .h and .m file, althought this isn't deemed good practice.
In Objective-C classes are a pair of interfaces and implementations. These don't have to be in separate files but often are and it is a good way to keep your file structure clean. Often classes represent a little factory and when you have a group of functions that can be grouped together it is a good idea to put them in a class together.
I'll admit to occasionally grouping a few classes together, either with the definitions of all in one .h and the implementations in one .m, or, where some classes are "private", with the definitions AND implementations of "inner" classes in the .m of the major class.
I think it's sometimes good to avoid a proliferation of files this way, and to group interdependent classes together.
You can also go the other way -- spread the definition and and/or implementation of a class among multiple files using "categories" -- but that's a touch ugly and should generally be reserved for extending frameworks classes with specialized functions. (And even at that, done with some apprehension.)

What's the best NAME for a NAMELESS Category you add at the top of a .m file?

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).

Changing cell appearance when editing UITableView _without_ using custom cells?

If I am using a custom UITableViewCell I can use the following methods to change the cell's appearance when transitioning state:
- (void)willTransitionToState:(UITableViewCellStateMask)state
- (void)didTransitionToState:(UITableViewCellStateMask)state
Is there a way to achieve this if I'm not using a custom tableview cell?
Edit: Please see Daniel Hanly's comment. Categories may be selectively applied using #import. My apologies to anyone that may have been misled by this answer. Relevant sections will be redacted for future reference.
Okay, attempt number two. As far as I am aware, there is no other documented way to implement the functionality you require without subclassing UITableViewCell. It's worth noting that Apple's docs on UITableViewCell specifically mention that the state transition methods are meant to be implemented by subclasses. That having been said, If you absolutely need to implement them without a subclass, there are a couple of less conventional solutions. Each comes with its own issues, and it may end up being unfeasible for you to implement them, but it's an interesting question nonetheless.
Disclaimer
If you only want a sane and relatively simple explanation, then consider the answer to your question to be "no, there is no way to do what you want." I only present the options below with the assertion that they will work. In no way do I endorse actually using them. Consider this my penance for providing my first answer with such an obvious flaw.
Option One - Categories
It is possible to get the functionality you're looking for by overriding the methods you listed in a custom UITableViewCell category.
The problem is that this approach would be a pretty bad idea 99% of the time. Once you define the category on UITableViewCell, those methods would be defined for all UITableViewCell objects throughout the app. Unless you want the exact same state transition functionality for every single table cell in the app, this approach isn't very helpful.
Option Two - Runtime magic
You can use the low-level Objective-C runtime functions to change the implementation of any method on the fly. Unlike the categories option, this approach is flexible enough to redefine the intended behavior whenever you need to, instead of being a one-shot deal.
For example, if you're trying to manage state transitions from a UITableViewController, you could do this:
CustomTableViewController.m
#import <objc/runtime.h>
- (void) customStateWillChange:(UITableViewCellStateMask)state
{
//custom UITableViewCell code
}
- (void) viewDidAppear:(BOOL)animated
{
//Store the original implementation
Method originalStateWillChangeMethod = class_getInstanceMethod([UITableViewCell class], #selector(willTransitionToState:));
originalStateWillChangeImplementation = method_getImplementation(originalStateWillChangeMethod); //variable declared in header file as type IMP
//Get the new implementation
Method newStateWillChangeMethod = class_getInstanceMethod([self class], #selector(customStateWillChange:));
IMP newStateWillChangeImplementation = method_getImplementation(newStateWillChangeMethod);
//Replace implementation
method_setImplementation(originalStateWillChangeMethod, newStateWillChangeImplementation);
//the rest of your viewDidAppear code
[super viewDidAppear:animated];
}
- (void) viewDidDisappear:(BOOL)animated
{
//restore the original implementation
Method originalStateWillChangeMethod = class_getInstanceMethod([UITableViewCell class], #selector(willTransitionToState:));
method_setImplementation(originalStateWillChangeMethod, originalStateWillChangeImplementation);
//rest of viewDidDisappear code
[super viewDidDisappear:animated];
}
This code may not suit your exact purposes, but I think it provides a useful example.
It's incredibly ugly though because the customStateWillChange: method defined here is only intended to be run as a part of the UITableViewCell class, but in this example it will be compiled as though it were part of the CustomTableController class. Among other annoyances, you would have to eschew the property dot notation, ignore compiler warnings and give up most if not all compile-time checks for that method's body.
Option 3 - Category with runtime magic
Exactly what it sounds like. Define any custom state change methods you like within a category (or several categories) on UITableViewCell. Be sure that each one has a separate name - adding two categories that each have a method of the same name will result in undefined behavior. Also, each one needs to have the same return type and argument types as the method it is intended to replace.
Then the references to [self class] in the above code would be replaced with [UITableViewCell class], and the customStateWillChange: method would be moved to the custom category. While still ugly, you can at least rely on the compiler to interpret the method bodies properly.
Of course, messing with the runtime adds a whole lot of complexity to keep track of. It could work fine, but it's not good design, it would take serious effort to ensure it worked safely and correctly, and it would be likely to bring anguish and despair to anyone maintaining it.
References
The Objective-C Programming Language - Categories and Extensions
Objective-C Runtime Reference
Absolutely. The UITableViewDelegate protocol specifies a number of methods to manage state transitions for the table view's cells. Take a look at the UITableViewDelegate Class Reference, specifically the methods listed under the heading "Editing Table Rows".
Edit
Sorry, you're right. The UITableViewDelegate methods don't respond to direct changes to the cell's properties. I've found a way that does work, but I'm going to put it in a different answer to avoid confusion.

Where to put "extra" implementation?

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.

iPhone Global Variable?

I have two views with their own .h and .m files of course. How can I declare a bool (or any variable for that matter) in one view and be bale to access it in another view?
Thanks.
Objective C is a superset of plain ANSI C, so you would create and use global variables exactly the same way as in old-fashioned C.
In exactly one .m or .c file, put:
BOOL gMyGlobalBoolVar = NO; // or YES, depending on whatever initial state is needed
I might place these in a centralized singleton class, such as your appdelegate .m file, or in a separate .c file, such as myGlobals.c. I usually place these after the #imports/includes but before any class, method, or function definitions to clarify that they can be accessed outside of any object or function.
In the .h files for all classes where you want to access gMyGlobalBoolVar, put:
extern BOOL gMyGlobalBoolVar;
Then just use them anywhere in the class:
if ( [ self dogHasFleas ] ) {
gMyGlobalBoolVar = YES;
}
The use of global variables is currently not "politically correct", but for quick code that you will never try to publish, reuse, extend, or hunt for gnarly bugs, they work just fine like they did in almost every computer and programming language from 50+ years ago.
You can just take a reference to the view containing the bool and get the variable using a getter.
If you want app wide variables, you could put them in the AppDelegate, but I highly recommend against that since it tightly couples classes.
Create a data model class. Instantiate it in your app delegate, and pass it along to your view controllers. Use Key-Value Observing to track changes to the model in your view controllers. See my answer here: How do I display and calculate numbers from a database on iPhone?
"Why shouldn't I use globals? It can't hurt just this once." This is a bad habit to get into. Avoiding global variables makes your code easier to read and reuse, easier to extend, and easier to debug.