I'm just wondering how exactly does a delegate method know when to be called? For example in the UITextFieldDelegate protocol the textFieldDidBeginEditing: method is called when editing begins in the textfield (provided I implemented this method).
So how exactly does the code to detect when to call textFieldDidBeginEditing:? Does the system just check if textFieldDidBeginEditing: is already implemented and if it is it runs that method? Is there something under the hood that I'm not seeing?
Exactly.
I can't vouch for how Apple's framework code is implemented under the hood, but an exceedingly common refrain is:
if ([[self delegate] respondsToSelector:#selector(someInstance:didDoSomethingWith:)]) {
[[self delegate] someInstance:self didDoSomethingWith:foo];
}
This allows you to have optional delegate methods, which appears to be your question.
The code doesn't 'detect when to call' a delegate method. The textField receives an event, and calls the method on it's delegate (which has the textFieldDidBeginEditing: method implemented).
In short, when you tap the textfield to start editing, the textField says 'oh, I'm editing now!' and internally calls [self.delegate textFieldDidBeginEditing:self], where the delegate is the instance in which you've set to be the delegate (usually a UIViewController subclass)
Related
I've performed a pretty exhaustive search of the documentation namely: UIViewController, UITextField, and UITextFieldDelegate, but I can't figure out where the method "textFieldDoneEditing" is originally declared.
I know that I have to use it in my ViewController to get the keypad to disappear in this manner:
- (IBAction)textFieldDoneEditing:(id)sender
{
[sender resignFirstResponder];
}
But is method part of a protocol that is inherently implemented by UIViewController?
Thanks
Without seeing the other code, I suspect this was connected to the textfield via interface builder connecting to the Editing Did End event. There is no textFieldDoneEditing method in any of UITextField parent classes.
I'm looking at code in a UIViewController that conforms to the UITextViewDelegate protocol and has an instance variable called someTextView.
someTextView.text = #"some text";
[self textViewDidChange:someTextView];
Is that safe? That doesn't look Kosher to me. Is it even necessary to call textViewDidChange:? Won't it get called automatically by someTextView.text = #"some text"?
I'm debugging this error iPhone Objective-C: Keyboard won't hide with resignFirstResponder, sometimes
read the discussion of textViewDidChange:
Discussion
The text view calls this method in response to user-initiated changes to the text. This method is not called in response to programmatically initiated changes.
If it's safe and a good idea to call (UIView-) delegate methods manually depends on the code inside of the method. Sometimes there are valid reasons to do this.
But your bug is most likely not caused by this snippet.
To be honest I don't know how to call it, so I'll try to describe it.
UIApplicationDelegate protocol has "application:handleOpenURL:" method. And if I implement this method in my ApplicationDelegate class, it will be called when somebody opens my urls.
details:
http://developer.apple.com/iphone/library/documentation/uikit/reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:handleOpenURL:
However, I'd like my other class (uiviewcontroller) to receive this call. To make a different example - you can create a few classes and each of them can get GPS position. Is it possible to do the same with UIApplicationDelegate protocol?
I searched a lot for this topic here, but I couldn't find any answer on how to do it. I know how to get my application delegate ([[UIApplication sharedApplication] delegate]), but it's not the case in this situation.
You can always tell somebody who came to objective-c from some other object oriented language, because their first instinct is to subclass, subclass, subclass. There's not a lot of subclassing in obj-c. You CAN, obviously, but it's not how things are conventionally done, especially with things that are as one-shot-ish as UIApplicationDelegate. The more Cocoaish Way is to use categories, or sometimes to create a new NSObject subclass that contains the would-be parent class as a property.
In this case, for sure subclassing is a bad idea. the UIApplication singleton can only have one delegate property. So if you create a new UIApplicationDelegate, you've got no place to hook to it.
Instead, smarten up your one delegate's application:handleOpenURL: method to catch the URL call and load up whichever UIViewController subclass (I know, I know: exceptions) is going to handle it.
The simplest solution would be to use an NSNotification. This will allow you to handle the handleOpenURL call wherever you need to without creating any unnecessary coupling between your application delegate and the class you want to handle it.
In your app delegate, handle the delegate method and forward the data on using NSNotificationCenter.
- (void)application:(UIApplication *)application handleOpenURL:(NSURL *)URL
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyApplicationHandleOpenURLNotification" object:self userInfo:[NSDictionary dictionaryWithObject:URL forKey:#"URL"]];
}
Now, wherever you need to handle this, simply register as an observer for the notification and pull the URL out of the notification user info dictionary.
Judging by your comments to Dan Ray's answer, it sounds like you are looking for something like Three20's URL-based navigation
I made a custom UITableView subclass and implemented this:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// scrolled...
}
Now, what I think is that UITableView may also love to get this message for some obvious reasons. However, when I don't forward that to super, for some reason, everything still works fine. Must I forward that guy to super? I mean...it's a delegate method implementation, but as far as I'm aware of, this would still override anything implemented in UITableView, or not?
Edit: I see...the delegate could be anyone. Never mind about this. BUT: What I have such a thing in a superclass, and make a subclass. How would I even know that the superclass does implement that method and I must forward it to super?
Short answer: no.
Those methods are defined in the UIScrollViewDelegate Protocol.
They are meant to be implemented in a delegate, which maybe only has NSObject as parent.
It does not override anything, as it's a delegate method.
The UIScrollView just does it's stuff, and calls the delegate method if a delegate is set.
This is a delegate method which means it gets called by your instance of UITableView for your convenience.
The scrolling happens and the UITableView internal code will call.
if ([delegate respondsTo:#selector(scrollViewDidScroll:)]) {
[delegate performSelector:#selector(scrollViewDidScroll:) withObject:[self scrollView]];
}
And so you use this method to implement additional functionality, for example activating a control when the tableView has scrolled a certain amount.
Hope this helps!
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.