I have just been learning iPhone apps development but I have a hard time in understanding what delegate actually means? Can anyone tell me with example what it does and how important it is? Thanks for any helps!
It's a key concept to understand conceptually so getting your head around how to think about it ahead of the technical details is important. Simply put, a delegate is a callback.
Two main scenarios to use delegates:
A class or control wants to abstract out the details on how to do work (like retrieve data).
Allow others to hook code into a pipeline.
Examples:
UITableView - a table view is just a control that knows how to render a list of cells. It handles all the heavy lifting of rendering, scrolling, etc... But, it has no idea how to load your data. So you implement a datasource delegate which has methods to get the cell data for a given row etc... That makes it easy on you. You just use the control and plug in the specifics for your data. The UITableView will do everything for you ... just answer a few specific questions for. A delegate answers those few specific questions.
A text control - you add a text control to your view and voila! you can type in it and alls good. But what if you want to do something when they start typing or when they're done typing? Well, the text control offers a delegate with methods that allow you to hook into the execution pipeline of the text control. It allows the text control to do everything for you and allows you to interject code where you need it. Many times, there's way to interject code to make a decision on whether something is allowed. The control will call back and ask, should I be able to do x? You can interject code and influence the behavior.
If you're creating a control or class, you can create your own protocol, datasource delegates etc... so your control can focus on doing what's advertised. For example, let's say you wanted to create a task control. You could:
First, create a contract. Hey, if you're going to provide data for my control, these are the questions I'm going to ask you. I'll take it from there... In this case, I'm going to ask you the number of tasks and I'm going to have you give me a task given the row number.
#protocol XXTaskBoardDelegate <NSObject>
-(NSInteger*)getTaskCount;
-(XXTask*)getTaskForRow:(NSInteger*)rowNumber;
#end
In the control or class, give the consumer a way to give us the delegate datasource class that will answer the questions the control will ask. At this point, the control is a pure control. It knows nothing about how you get your data. It's asking for an object (id) that implements a contract/protocol. id
#implementation XXTaskBoard
- (void)setDelegate:(id<XXTaskBoardDelegate>)newDelegate
{
// the control stores the delegate so it can callback and ask you questions.
}
Then, for the delegate class, in the header declare you implement that formal protocol
and in the implementation m file you provide the code.
#interface AppController : NSObject<XXTaskBoardDelegate>
{
//...
}
then, implement it in the implementation
#implementation AppController
- (NSInteger*)getTaskCount
{
return [model queryTaskCount];
}
- (XXTask*)getTaskForRow:(NSInteger*)rowNumber
{
return [[model tasks] getItem:(NSInteger*)rowNumber];
}
A delegate is an object that another class can pass messages to. In practice delegate classes have to conform to a delegate protocol.
For instance we will take a subclass of a table view controller. This is a delegate for your table view. First you define that it is a table view delegate by doing this:
MyTableViewController : UITableViewController <UITableViewDelegate>
This says that class MyTableViewController is a subclass of UITableViewController and CONFORMS to the UITableViewDelegate protocol.
Setting [tableView setDelegate:self] (or defining it as such in IB) then passes the self object to the tableview in order for the tableview to send messages to it.
The main message it sends is the didSelectRowAtIndexPath message which tells your class that the user has pressed a table view cell.
So the object that takes the click event (the table view) passes on the message that the cell has been clicked to the delegate object (which in this case is your MyTableViewController object).
Delegate protocols exist so that you can make sure that the delegate object has the necessary methods to deal with your messages. Methods in a delegate protocol can be #optional or enforced. Any methods that are optional don't have to be defined. In your MyTableViewController class the method didSelectRowAtIndexPath is optional - you don't have to have it. If the table view doesn't find the method it just won't call it.
However the cellForRowAtIndexPath is necessary and without it your app won't compile.
I hope this helps and is straightforwards for you. If you need any more info let me know.
Delegates are just way of getting callbacks from something. You pass a delegate (a pointer to an object that conforms to a protocol) to something and when it has new data for you or when an event occurs that something make a method call on the delegate.
For example, when events occur, like your app is put into the background or the app is about to terminate the UIApplication object will call your application delegate to let it know. When a CLLocationManager has a new GPS position is will call your delegate to pass it the new position. UITableViews call their delegates to get UITableViewCells to display in the table. There are many uses of delegates in iOS.
Related
I have recently started to learn about programming for the iPhone and after going through numerous online tutorials and books (most of which tell you to write this here without offering any explanation as to why or how stuff is working) I still have many questions unanswered and it would be great if someone could help me clarify them.
Here goes:
1) In Interface Builder, what is file's owner, first responder, and a delegate, and where is the actual code that draws the view?
2) When using Interface Builder and you add components to the screen, I understand that Interface Builder doesn't automatically write the code for you, but how should I handle the events fired by the different components? From a best design practice view, should each component have its events handled in a separate file? (would such file be the component's delegate ?) or is it better to just make the viewcontroller class implement all of the interfaces of its components?
3) When creating a UITableView for example, and I define the function:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [listOfItems count];
}
I am saying that the object tableView of type UITableView has this callback function. Right? So in case I have another UITableView named MyTableView I should write a function as such:
- (NSInteger)MyTableView:(UITableView *)MyTableView numberOfRowsInSection:(NSInteger)section {
return [listOfItems count];
}
There's some big questions here and very hard to answer in a stack overflow post.
1)
A. What is the File Owner?
The nib is a file right? So what would own the nib file? Well the owner is whatever object you call initFromNib: on.
AClassName *theOwner = [[AClassName alloc] initFromNib:#"nibfile"];
A nib file is just a freeze dried object, a description of an object, a serialization of an object. The object is often freeze dried with a bunch of helper objects to it can be unfrozen and ready to go. Remind me of how Egyptian Pharaohs were buried with many of their servants and many of their possessions, they would be ready to go in the after life. The owner is the main object that has been frozen. In a frozen state (the nib file) the owner is frozen and you can't work with it. When you unfreeze by loading the nib file the main object that's unfrozen is the owner.
B. What is the First Responder?
When you interact with your program by touching the screen, shaking the phone, typing on the keyboard the program must respond to that event, many other frameworks call this handling the events or actions. The First Responder is the first object that gets to respond to the user's interactions. This will typically be the NSView that the user touches, which responds by redrawing itself and sending updated information to the View's Controller (Remember, NSView inherits from NSResponder - now you know why).
It's in the nib file so you can override the typical behavior. The Cocoa Framework is used for the Mac too so programmers might want to have a single object handle keyboard input rather than letting each view handling the keyboard input itself. This is rarely used in iPhone programs directly, because you typically want what the user touches to respond to user interaction (redraw itself) and pass on updates. So you can usually just ignore it in the nib file.
C. What is a Delegate?
What does a person do when they delegate? They tell someone else to do this job for them and report back. People delegate all the time. I delegate fixing my car to a car mechanic. I delegate cooking dinner to the cook at a restaurant I'm dining at. "Johnson, I need you to write that TMI Report for me" said my boss delegating to me for I was company expert on TMI. Classes in the code are no different.
The delegate in the Interface Builder is the Application's delegate. The UIApplication class is going to hand off lots responsibilities to it by sending messages to methods defined in the UIApplicationDelegate Protocol. For instance if your delegate implements the applicationDidFinishLaunching: method it'll receive a message after the instance of UIApplication has initialized and finished its startup routine.
D. Where is the drawing code?
Apple has provided with the Framework in classes like NSView, NSWindow, NSTableView and it's not open-source so you can't view the source code. But the reason the window launches and appears when your first run an application built on one of Apple's templates before adding your own code is due to what occurs in the file main.m.
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
The call UIApplicationMain(argc, argc, nil, nil) starts everything rolling. It loads in the nib file to unfreeze the UIApplication object and other objects in the nib file. Then it asks the application to start it's main loop. Once unfrozen the UIApplication object (the nib's owner) then tells it's MainWindow to display on the iPhone Screen and keeps the UIApplicationDelegate in the loop about what's going on.
Well that's my answer to 1). Took a while to write I hope it helps. One thing that really helped my understanding was: creating a new Window-based Application project, deleting the MainWindow.nib and then attempting to recreate it from an empty nib file, so that it functions the same way.
Here goes:
In Interface Builder:
The "file's owner" is the Objective-C class to which your interface belongs. Usually for a view controller this means the custom view controller subclass you're creating.
The "first responder" is mostly there for behind-the-scenes handling of events; it's used to figure out when your class and interface handle events, and when to pass them up the responder chain.
A "delegate" is a general term for any object which receives messages about the actions of another object. In Interface Builder, it can sometimes be used to pass actions around between objects, or can refer to the "app delegate," which is a class that exists in almost all iOS projects and receives messages about the behavior of the application itself.
To handle events from your GUI components, the generally accepted thing to do is to define a method with return type IBAction in your view controller implementation, then hook it up to an event from a component. Then when that event is triggered, your method is called. It's not usually necessary to break them out into a lot of separate files unless you have a very complex structure.
Not quite. If you have another table view, you can call it myTableView, but you should still hook it up to the same table view delegate and data source, and the method name doesn't change. Let's break the first part of this method signature down:
The (NSInteger) means this method returns an integer
The phrase tableView: is part of the method name, and shouldn't be changed. A table view will always call the method tableView:numberOfRowsInSection: for the information it wants, so changing to `MyTableView* would break.
(UITableView *) means the first argument is of type UITableView
tableView means that the name of the variable inside this method for the calling table view is tableView
Think about reading through the View Controller Programming Guide - it covers a lot of these concepts and links to more documents that explain delegation, table views, etc.
1.) File owner is the (generally) UIViewController subclass associated with the View you are building in IB (what you call GUI builder is actually termed Interface Builder)
First Responder is generally used in the background by the program to indicate what has control at the moment (generally don't do much with this)
The delegate is the file that receives the actions done on the view (and thus must implement how to handle these), (see below)
2.) Generally you will have a ViewController code file for each Interface Builder View (the File Owner). Generally this will be where the actions are handled for specific components (say, clicking on a button). You will set up variables (and methods for button clicks and etc) to handle each component from IB (a textfield or button is an IBOutlet, while an action like clicking on a button is an IBAction) As far as best design, I believe you should have a delegate for each view that does all the above, but I generally just use the ViewController as the delegate and implement it there (for relatively simple views)
3.) No, the parameter name (which is what tableView and MyTableView are in your examples) are used inside the function to indicate the value that you passed it. When you call this function you would call it like [myTableView numberOfRowsInSection:2]; and inside the function anything you needed from "myTableView" is actually referenced by the parameter name tableView...That is for any function, but for UITableViewDelegate methods (like the one you are referencing, it will be called automatically by the UITableViewController if it's delegate is set to the file you define this function.
Wow looking back thats some blocks of text, my best advice would be to get Beginning iPhone Development by Mark and LaMarche, it addresses all this very well.
I'd also suggest looking at some of the very basic examples in the Apple documentation to get a gist for how Interface Builder and delegates are properly used.
Edit: as a commenter pointed out, the Stanford iOS course is fantastic and where i learned the basics (along with the book above)
See my answer to this question for an explanation of what "loading a xib file" means and the meaning of File's Owner and outlets. It's perhaps a bit advanced for a beginner, but if you really want to know the "what" of what's going on and figure out the "why do it this way" for yourself, it's probably a good read:
Put a UIView into a UITableView Header
Here is my dilemma. I would like to have a text box and a button. The user types in text and then presses the button. Once the button is pressed, a text message window (using MFMessageComposeViewController) comes up. I don't know how to set this up. The problem is that the TextBox will require a delegate (UITextFieldDelegate) and the MFMessageComposeViewController will require an MFMessageComposeViewControllerDelegate. How can I have a .h file that declares a view that is more than one delegate?
I'm new to iPhone programming so any help on how to have an interface view that handles more than one delegate (so that I can have multiple types of controls in my view) would be really helpful!
A delegate does not need to be a view. Indeed, in most cases it probably shouldn't be. Often you will make a controller object the delegate, although this depends a lot on what you're doing.
The delegate protocols you need (MFMessageComposeViewControllerDelegate and UITextFieldDelegate) are quite distinct, so a single object can readily implement the methods of both without any confusion. But even if you are the same delegate type for several objects, the methods will be passed a pointer to the calling object so you can decide what to do case-by-case if necessary.
If you just mean how do you declare your class as implementing both protocols, you would do this:
#interface MyDelegate : NSObject <MFMessageComposeViewControllerDelegate, UITextFieldDelegate>
{
...
}
...although this presupposes that the protocols are formally required, which I don't think is the case here. In which case such a protocol list is unnecessary.
Otherwise, I probably am not understanding your question...
EDIT: OK, it seems like what you're looking for is how to link up the delegates at runtime. This varies according to the particular class, but for MFMessageComposeViewController you do this:
MFMessageComposeViewController* composer = ...;
id<MFMessageComposeViewControllerDelegate>* delegate = ...;
composer.messageComposeDelegate = delegate;
Easy, no? In this case the protocol is required, so you'd have to include it in the interface as described previously.
In general, if an object uses a delegate for anything, it will have a property or a method to allow you to set it, which you'll find in the documentation. Eg, in this case: Properties for MFMessageComposeViewController.
Note that delegate properties are conventionally weak references, so the objects in question need to be retained somewhere in your application.
I'm working through an iPhone tutorial (link text and it has me put in some code (a few times throughout the various tutorials) but it doesn't explain it at all.
In this code:
todoAppDelegate *appDelegate = (todoAppDelegate *)[[UIApplication sharedApplication] delegate];
What exactly is an appDelegate? What does the "delegate" at the end of the instantiation mean? Actually, what does the whole thing mean? (UIIapplication sharedApplication)?
I am a .Net programmer if that helps someone explain it better. I hate learning through tutorials because I always need to know what EVERYTHING does and no one explains everything.
Let's back up a little bit.
The square brackets ([ ]) are Objective-C's method calling syntax. So if Cocoa had a C# syntax, the equivalent syntax would be:
TodoAppDelegate appDelegate = UIApplication.sharedApplication.delegate;
In C#, you would use a static class for a class that only has a single instance. In Cocoa, the Singleton pattern is used to accomplish this. A class method (in this case, sharedApplication) is used to retrieve the single instance of that class.
Delegates in Cocoa are not like the delegate keyword in C#, so don't be confused by that. In C#, you use the delegate keyword to reference a method. The delegate pattern in Cocoa is provided as an alternative to subclassing.
Many objects allow you to specify another object as a delegate. Delegates implement methods that those objects will call to notify them of certain events. In this case, UIApplication is the class that represents the current running application (similar to System.Windows.Forms.Application, for example). It sends messages to its delegate when things that affect the application happen (e.g. when the application launches, quits, gains or loses focus, and so on.)
Another Objective-C concept is the protocol. It is similar in principle to a .NET interface, except that methods can be marked as #optional, meaning they classes are not required to implement the methods marked that way. Delegates in the iPhone SDK are simply objects that conform to a specific protocol. In the case of UIApplication, the protocol delegates must conform to is UIApplicationDelegate.
Because it's not required to implement every method, this gives the delegate flexibility to decide which methods are worth implementing. If you wanted to, for example, perform some actions when the application finishes launching, you can implement a class that conforms to the UIApplicationDelegate protocol, set it as the UIApplication instance's delegate, and then implement applicationDidFinishLaunching:.
UIApplication will determine if its delegate implements this method when the application finishes launching and, if it does, call that method. This gives you a chance to respond to this event without having to subclass UIApplication.
In iPhone applications, developers also frequently use the app delegate as a kind of top-level object. Since you don't usually subclass UIApplication, most developers keep their global application data in the app delegate.
A delegate is just an object that implements certain methods (basically callbacks). The NSApplication docs explain what its delegate is supposed to do and what messages it needs to respond to to.
And this isn't instantiation. The snippet you posted above doesn't create anything. It accesses whatever object is set as the application's delegate. [UIApplication sharedApplication] gets the object representing the application, and sending delegate to the application gets its delegate (if any).
to add more to the mix of responses and another point of view, delegates are objects that can (but don't necessarily need to) do work for another object.
So let's say you have objectA, and can assign to it a delegate (let's call it delegateObject).
From objectA's point of view, there are certain bits of work that may need to be done. Depending on the context, the actual work and the results of such work can be different.
So instead of having objectA implementing a method for all these instances, we'll say... let's have another object, delegateObject, do the work... and as long as the results are returned in the proper format, we don't care what delegateObject did to get there.
objectA will first check that delegateObject exists and that delegateObject has implemented a method to do the work asked of it.
To accomplish this, NSObject (which every Cocoa object inherits from) has this method:
- (BOOL)respondsToSelector:(SEL)aSelector
and objectA would do a simple test before sending a message to delegateObject, for example:
if ([delegate respondsToSelector: #selector(someMethod:sender:)])
{
[delegate someMethod:#"stuff" sender:self];
}
and because objectA only sends a message to its delegate if one's been assigned, delegate is not retained by objectA.
if we were to use UITableView as an example, it has a lot of UITableViewDelegate methods. One of them is:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
every time the user touches a row in a table, the UITableView object will first check that there's a delegate, if there's a delegate, it'll then check that the delegate has implemented the above method. If it does, then it'll send the message to the delegate. This method expects no return value, and UITableView will go about its merry way, regardless of what the delegate does. And if there is no delegate that implements that method, then nothing happens.
I would like to gain a better understanding about the delegation. Can somebody please paste a good code sample of delegation and explain how it works?
There is a pretty good example at: http://en.wikipedia.org/wiki/Delegation_pattern#Objective-C_example
In this example, MyCoolAppController creates and object of type TCScrollView, and sets the "delegate" property of the TCScrollView to self. This means that when the TCScrollView calls
[delegate scrollView:self shouldScrollToPoint:to]
it is asking the MyCoolAppController (the delegate of the TCScrollView) to perform some calculations and see if it is ok to scroll. You can say "MyCoolAppController is the delegate of TCScrollView" to describe this; TCScrollView asks MyCoolAppController to do some work on its behalf.
Do you mean .NET or Java or some other language delegate?
A delegate in .NET parlance is nothing more than a function pointer, or in other words a variable that points to a block of executable code. They can be used in may ways. One way is to use them in the context of events. Lets say you have an ASP.NET page and you are using the MVP (Model View Presenter pattern on that page). You want your presenter to be notified of the click event of the save button on the view. You can define an event on the views interface, but in order to subscribe to that event and to take action on it you need to register a method that gets fired when the event is raised. For example:
public class ClassThatRegistersForEvent
{
public void InitializeView(IView view)
{
view.SaveButtonClickedEvent += delegate{
// do stuff in here when the event is raised
}
}
}
public interface IView
{
event System.EventHandler SaveButtonClickedEvent;
}
Here's an answer I wrote explaining delegation: https://stackoverflow.com/questions/1089737#1090170
A delegate is a way to respond to events. In other languages you would probably do this by subclassing. For example, say you have a table view. You could subclass the tableview and override the tableView:didSelectRowAtIndexPath: method, but that would get messy and create an unnecessary subclass (along with the fact that its not reusable) Instead, you create a TableViewDelegate class and tell your table view about it (tableView.delegate). This way, the method will automatically get called when something happens. This is a really clean solution to event-handling.
After you write a few apps that involve delegates (table views are the big ones), you'll get the hang of it.
for example we use this method in the tableview
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 16;
}
i want to learn we don't call this method in anywhere but application reads this value how is it being? there are a lot of methods like this we did not call.
Your object has been set as the data source of the UITableView somewhere. Most likely, by making a connection in InterfaceBuilder, though it is straightforward to do so in code by setting the dataSource property of the UITableView:
- (void) setUpMyJunkMan
{
myTableView.dataSource = self;
}
Once you have set your object as the data source, the table view will invoke the method as needed to determine what it needs to draw or how it needs to respond to events.
Your object is required to implement the UITableViewDataSource protocol (though, if you connected the data source via InterfaceBuilder, there may not be a complaint if you don't -- it is more of a compile time validation than a runtime one).
If you look at the declaration of UITableViewDataSource, you'll see that a number of methods are #optional. The rest are #required; you must implement them to fulfill the contract of the protocol.
This is the key difference between data sources and delegates. Delegates can optionally implement any of the declared methods. Data sources create a much more formal relationship between the two objects wherein some of the methods must be implemented.
An easy way see why a method is being called - set a breakpoint, run in debug mode, and then look at the stack trace.
For this particular case - It's being called automatically by the framework when it renders the table view.
I think you really need to take a look at The Table View Programming Guide so that you have a good understanding of what methods you need to override (and not override) when using Table Views. If you are extending the TableViewController class the framework does a lot of the heavy lifting and you barely have to write any code.
numberOfSectionsInTableView: is being called by the table view.
You implement numberOfSectionsInTableView: as part of the UITableViewDataSource protocol. Each UITableView is given a dataSource. Normally, UITableView will be constructed by a UITableViewController which will set itself as the view's dataSource.
When the view is shown, it calls numberOfSectionsInTableView: on its dataSource.
This is explained in the Table View Programming Guide for iPhone OS.
This is part of a Delegate Interface.
At some point in your application (possibly in your UIBuilder) you have specified that the object that contains the method is actually the delegated object. This means that when you want to adjust the behaviour (in this case of a UITableView) you can without actually extending UITableView but mearly changing the delegate methods.
basically the UITableView class will look somehting like this.
- (void) AMethodinUiTableView
{
int colums =[self.delegate numberOfSectionsInTableView:self];
}
for more info i would check out delgate programing and selectors.