Why are IBOutlet Properties declared in a class extension? - objective-c

When I create a new single view application, the UIViewController file that is generated has an extension (I think it's an extension) in the implementation file.
//
// ViewController.m
//
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
//...
#end
And the convention seems to be that IBOutlets are declared as properties inside this extension. Why is this? What kind of behavior does this result in that is different from declaring it in the header file interface?

Properties in the header files are public, property declarations in the implementation files are private. It's up to you to choose. You can connect them directly from the interface builder into the desired file.
I can't understand your concern about extension - this code is fine. Could you explain this? (i can't comment - too less reputation, sorry)

Related

why do AppDelegate being declared again at AppDelegate.m

I'm just a newbie who follow iOS dev, and when I create new single application by using Xcode, I notice that #interface AppDelegate() being declared again in AppDelegate.m file.
but to be honest, I really don't understand why, I already see #import "AppDelegate.h" at begin of AppDelegate.m file, why couldn't I directly use #implementation AppDelegate after #import "AppDelegate.m"?
There is a difference here. The declaration of the AppDelegate Interface in the .m file is actually a class extension. Notice the () after the interface declaration.
As mentioned in the documentation:
Class extensions are often used to extend the public interface with
additional private methods or properties for use within the
implementation of the class itself.

Split Objective-C Code into multiple files

I often feel the need to split the Objective-C code into multiple files for better readability. I want to avoid making classes and call them. I want simple import (like in php).
If someone could please refer a working example.
I think you're looking at categories in this case:
All you have to do is to create a new .h .m pair and in the .h file:
#import MyClass.h
#interface MyClass(Networking)
//method declarations here
#end
and in the .m file:
#import MyClass+Networking.h
#implementation MyClass(Networking)
//method definitions here
#end
And in MyClass.m file - do #import MyClass+Networking.h and you're all set. This way you can extend your class.
You say “I want to avoid making classes and call them.” You need to overcome your fear of adding classes. If you feel the need to split a class's implementation into multiple files, chances are you are trying to do too much in a single class. You need to let that class hand off (“delegate”) some responsibilities to other classes.
That said, there are a couple of ways you can split up a class's implementation. The better way, short of fixing your bloated class design, is to use categories or class extensions. You can read all about categories and extensions in The Objective-C Programming Language. Note that the linker will merge the categories and extensions into the class when it creates your executable file, so there's no runtime penalty for using categories or extensions on your own classes.
The worse way is to use the C preprocessor's #include directive to paste multiple files together. You can just take some methods out of the implementation file and stick them in new “fragment” file, then #include the fragment file in the implementation file. Doing this will make it harder to understand your source code. I would not recommend doing this, but here's an example anyway:
MyObject.m
#import "MyObject.h"
#implementation MyObject
- (void)aMethod { ... }
#include "MyObject-moreMethods.m"
#end
MyObject-moreMethods.m
// Note: do not include this target in the “Compile Sources” build phase of your target.
// And **NO** #implementation statement here!
- (void)methodTwo { ... }
- (void)methodThree { ... }
[EDIT/UPDATE -- I have abandoned the approach described below in favor of using categories, as mentioned in some of the other answers. My typical situation is that as a view has control components added, the View Controller file becomes unwieldy as code is added to accommodate the various delegate and data source methods for the controls. Now I add in code stubs in the view controller file, then implement them for real in a class category. For instance, I might have an AlbumViewController screen that has a search bar and a collection view, so I create categories AlbumViewController+SearchBar and AlbumViewController+CollectionView. This allows the View Controller class to stay at a reasonable size, without incurring any of the drawbacks I listed below for included files. The only downside is that any instance variables, ie properties, must be declared publicly for a category to access them.]
I also want to split my files up, but think categories are not the correct solution in some cases. For example, as nibs grow to include multiple objects (such as tables, buttons, nav bars, tabs, etc) the need for placing all the supporting methods in the viewcontroller.m file can lead to a very large and unwieldy file.
For this discussion, I am going to refer to the original/standard .m file as the parent, and the subsidiary .m files as children.
The goal is to have a single parent .h and .m, and multiple child .m files each of which can be edited independently, but compiled as if all the child .m files were in the parent .m file.
This would be useful if one wants the ability to, for instance, place all table related methods in a file, edit it, and then have it compile as if it were included in the viewcontroller.m implementation file. It seems this is possible, but requires a little effort, and has one (possibly serious) drawback.
The thing to keep in mind is that there are two distinct tools being used: the IDE (which provides intelligent source editing) and the compiler/make system which turns a project's source code into a runnable app.
To get the IDE to work as expected, the child files need to appear to be part of the implementation of the class. This can be accomplished by wrapping the #implementation and #end directives in conditional compilation macros. When editing a file on its own, the IDE considers the child files to be the body of the class, but the compiler doesn't.
To get the compiler to not complain, you can't have the child files considered part of the target -- instead they get pulled in through the preprocessor #include directive. This can be accomplished by not adding them to the target when the file is created (or added to the project), or by removing them on the "Build Phases" -> "Compile Sources" pane.
You then #include the child .m files within the body of the parent .m files. The compiler loads them "in place" and compiles the source as wished for without complaints.
The drawback of this approach (so far) is that the debugger does not recognize the child methods, and will not break on breakpoints put on them. For that reason I suggest that this approach only be used either after the code is thoroughly tested, or for code chunks that are relatively trivial and well-known, such as table delegate and data source methods.
Here are the .h and .m files for a project with a table and a text field in a nib, with the supporting delegate methods defined in child .m files. In the nib, the interface objects are wired up normally, and have the delegates set to the file owner.
File (parent) "MyViewController.h":
#import <UIKit/UIKit.h>
#interface MyViewController : UIViewController
#property (retain, nonatomic) IBOutlet UITableView *myTable;
#property (retain, nonatomic) IBOutlet UITextField *myTextField;
#end
File (parent) MyViewController.m:
#import "MyViewController.h"
#define VIEW_CONTROLLER_MAIN_BODY 1
#interface MyViewController ()
#end
#implementation MyViewController
#include "MyViewController_TableMethods.m"
#include "MyViewController_TextFieldMethods.m"
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
[_myTable release];
[_myTextField release];
[super dealloc];
}
File (child) MyViewController_TableMethods.m:
#import <UIKit/UIKit.h>
#import "MyViewController.h"
#ifndef VIEW_CONTROLLER_MAIN_BODY
#implementation ViewController
#endif
#pragma mark -
#pragma mark Table View Common Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
static NSString *myIdentifier = #"myCellIdentifier";
static UITableViewCellStyle myStyle = UITableViewCellStyleSubtitle;
UITableViewCell *cell = [self.myTable dequeueReusableCellWithIdentifier:myIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:myStyle reuseIdentifier:myIdentifier] autorelease];
}
cell.textLabel.text = #"Title";
cell.detailTextLabel.text = #"Details";
cell.accessoryType = UITableViewCellAccessoryNone;
return cell;
}
#ifndef VIEW_CONTROLLER_MAIN_BODY
#end
#endif
File (child) MyViewController_TextFieldMethods.m:
#import <UIKit/UIKit.h>
#import "MyViewController.h"
#ifndef VIEW_CONTROLLER_MAIN_BODY
#implementation MyViewController
#endif
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
self.myTextField.text = #"Woo hoo!";
return YES;
}
#ifndef VIEW_CONTROLLER_MAIN_BODY
#end
#endif
This is a good indication that your class is just too large.
One approach: Use categories. Declarations can often stay in the header. Then your implementations may be divided. Just make sure to specify the category you are implementing, so the compiler may match it with its declaration, and inform you when you miss a definition.
A good way to break-down your big class is group functionality in Categories (like Apple does in UIViewController). For a big class, I generally group methods and properties related to their repective functionality and then
In base header file, I split
#interface SomeClass : NSObject
#property (strong, nonatomic) BaseProperty *sp;
- (void)someMethodForBase;
#end
#interface SomeClass (FunctionalityOne)
#property (strong, nonatomic) FuncOne *fpOne;
- (void)someMethodForFunctionalityOne;
#end
#interface SomeClass (FunctionalityTwo)
#property (strong, nonatomic) FuncTwo *fpTwo;
- (void)someMethodForFunctionalityTwo;
#end
Because you can't add property in category (You can't add new iVar and property don't synthesis in category) so you declare it in implementation of base Extension again.
#interface SomeClass()
#property (strong, nonatomic) FuncOne *fpOne;
#property (strong, nonatomic) FuncTwo *fpTwo;
#end
#implementation SomeClass
//base class implementation
- (void)someMethodForBase {
}
#end
Implementing respective functionality in SomeClass+FunctionalityOne.m
#implementation SomeClass (FunctionalityOne)
#dynamic fpOne;
//Functionality one implementation
- (void)someMethodForFunctionalityOne {
}
#end
Implementing respective functionality in SomeClass+FunctionalityTwo.m
#implementation SomeClass (FunctionalityTwo)
#dynamic fpTwo;
//Functionality two implementation
- (void)someMethodForFunctionalityTwo {
}
#end
This way I cleanly organise my big class implementation into small classes and all class functionalities information grouped in single base header for read and import.
its better to use Categories in iOS keep the code clean .
I know this is an old thread and the Objective C gods won't like this solution, but if you need to split files, create a new .m file and paste your code there. Then, #include "yournewfile.m" after #implementation in the .m file where you want to include it. The trick to avoiding a compiler error is to go to the Build Phase and remove "yournewfile.m" from the Compile Sources.

avoid warning when doing class extention

I want to do the following :
#interface UINavigationController ()
-(void)removeFromNavigationStack:(Class)aClass;
#end
and in .m file
#implementation UINavigationController
-(void)removeFromNavigationStack:(Class)aClass {
}
but in the .m file there are a lot of warning like "Method definition for 'initWithRootViewController:' not found"
how can I avoid this ? I've tried including but still have the warnings
Thanks
Since you're dealing with UINavigationController, a UIKit class, you probably want to go with a category, instead. Extensions need to be defined within the main #implementation block of the class's implementation, and you don't have access to that for UINavigationController
From the docs:
Class extensions are like anonymous categories, except that the methods they declare must be implemented in the main #implementation block for the corresponding class. Using the Clang/LLVM 2.0 compiler, you can also declare properties and instance variables in a class extension.
Add your class extension in your .m file.

XCode 4.2 why do I see #interface both inside .h and .m files

why do I see #interface twice( inside .h and .m files in this UIViewController files I've created. the one in the .m seems to be like a constructor. is it?
.h file
#interface BlackTimer : UIViewController
#end
.m file
#interface ViewController ()
#end
usually in the .m file you put all the declarations for private methods
it's a good use to write the word "private" (or something similar) like this:
#interface ViewController (private)
-(void)myPrivateMethod;
#end
The #interface in the .m file is called a class extension. Here is a good link explaining it. Hope this helps.
And here is the Apple documentation on class extensions.
The #interface ViewController () definition in the implementation file (.m) is an anonymous Category. It allows to define ivars, properties and messages your class implements without exposing them to other objects importing your public interface (.h).

Closing panel in one source file from a separate source file

This is what I got so far.
- (IBAction)HUDPanelDictionaryHide:(id)sender{
extern NSPanel HUDPanelDictionary;
[HUDPanelDictionary close];
}
This obviously does NOT work.
The HUDPanelDictionary is declared in a separate .h and .m file for an .xib file. I need to close this panel from the other .h and .m file for another .xib file. Sorry I'm being so vague!
Any ideas??
Elijah
You need to #import the header containing the declaration of HUDPanelDictionary.
For example:
#import "HUDPanelDictionary.h"
#interface MyController
- (IBAction)hideDictionaryPanel:(id)sender {
[HUDPanelDictionary close];
}
#end
I would also name things differently, for example "DictionaryHUD" rather than "HUDPanelDictionary." "Panel" is redundant with "HUD," and you should care more about its intent than its position in the class hierarchy.
Another thing I would do is make DictionaryHUD an NSWindowController subclass, and have it expose a singleton shared instance rather than use a global variable to point to the panel itself. Then the code above would look like this:
#import "DictionaryController.h"
#interface MyController
- (IBAction)hideDictionaryPanel:(id)sender {
[[DictionaryController sharedDictionaryController] hideDictionaryPanel:sender];
}
#end
This puts the primary responsibility for your dictionary panel/HUD on an instance of a single controller class, to which other controllers (say one that manages your main window's toolbar) can forward their interactions. You could even put the dictionary HUD window controller in the responder chain to have it automatically handle actions like -hideDictionaryPanel: so nothing needs to do that kind of forwarding.