Using an IBAction method when it is not called from an action? - iphone

Are there any issues when using IBAction when it is not actually called from a user's action?
If you have an action like
-(IBAction)sayHello:(id)sender;
You can call it from within your class like:
[self sayHello:#"x"]
The #"x" doesn't do anything, it just fills in for the sender.
You can actually create an IBAction method without (id)sender
-(IBAction)sayHello;
and call it from both user's actions and from within the code, but then you won't get any useful sender info from the interface. What's the 'correct' way of filling in for the sender, when calling from the code? And can you create sender info to send when it's called from within the code?
Just trying to figure it out.

I think a good practice for OOP is to refractor the method
-(IBAction)sayHello:(id)sender;
to another method called: -(void)sayHello;
and inside the method
-(IBAction)sayHello:(id)sender {
[self sayHello];
}
If other methods want to call the sayHello:(id)sender action to do some job, it can call the sayHello. The method name should make sense for the client to call it without a problem or work around. It will help you when you have to test or debug

The sender should be a UI component. So if in your class you have, say, a UIButton...
UIButton *button;
Then you can just send it as parameter to the action:
[self sayHello:button];
Insider the method, no matter if it is called from the UI or in some simulated way, you can have some logic to detect who the sender is, and behave differently based on that. This way, multiple buttons or other components can reuse the same action method.

Unless you're actually making use of the sender parameter (see Jaanus's answer for more on that), you're fine with passing nil for it when calling the method from code.

Related

What does obj.delegate=self mean?

What does it actually mean to set the delegate of a textfield?
For example: txtField.delegate = self
"In short, that you are receiving calls from the txtField. You are setting the object 'self' as the delegate for txtField."
"That means that your 'txtField' will receive events from itself
These two answers essentially mean the same thing. But seemingly contradictory. But the first makes more sense to me. I can see why a beginner gets confused, I've been there!
Basically one is the caller one is the receiver Think of it as a chef in a kitchen call his assistant to cut up some onions. In this particular case, txtField is the chef, "self" is the assistant. txtField orders self "Do this, this and this!" Like it or not the assistant has to oblige cuz he has wife and kids to feed. :)
It means that self will be the recipient of certain method calls that are made in response to actions on the text field.
In short, that you are receiving calls from the txtField. You are setting the object 'self' as the delegate for txtField.
Delegating is a programming pattern that is widely used in Objective-C.
The basic idea is let an object delegate some tasks to another object. For example, your UITextField object delegate some tasks to your view controller. In this case, your UITextField object becomes a delegating object, and the view controller the delegate of the UITextField object. The delegating object sends certain messages to its delegate in order to get necessary information, or to notify certain events, etc.
That means that your 'txtField' will receive events from itself (kind of a weird example, maybe a larger source code section could be provided?)
For some of its methods, the textfield (any object in a class using the delegation pattern) is going to try to call some other object to so that that object can customize some of the textfield's behaviors. The object that the textfield will try call is called it's delegate. The delegate is initially set to nil, so, by default, no customization happens.
If a class has a line of code like: textfield.delegate = self; then it says that this object in this class wants to get called to handle the textfield's customization for certain of the textfield's defined delegate methods.
It means the actual class where 'txtField.delegate =self' is called will receive callsbacks from events. This is often a convenient way to do things.

iPhone identify button pressed

I have a view with several buttons that all have the same target and action.
At the moment the action is #selector(doSomething).
I need to be able to determine which button is pressed but I'm not sure of the best way to do this.
The method doSomething is declared as...
-(void)doSomething;
Is there a better way to declare this so I can get more info out?
Thanks for any help!
Oliver
If you declare the method as
- (void)doSomething:(UIButton *)sender
with the corresponding selector #selector(doSomething:), then you can check the identity of the sender using either of the methods Joshua suggested.
Target/action messages provide the sender as the argument. In your case, the button that called the message is the sender. You could ask it for its -tag (which you can set in IB) or you could name it as an outlet and test for equality: if (sender == myButtonOne) ...

How should I deal with the need for multiple callbacks for the same delegate in Objective-C?

I have created a library which can download JSON data which is then placed into an NSDictionary. I wrap this class with a simple Twitter engine which allows me to pull my friends timeline, post an update and post an update with my GPS location. From my limited experience with Objective-C the way to connect everything is with delegation. I set a delegate property which calls back the asynchronous result to either a selector or a method signature. I can even create an optional or required interface on the delegate which will allow Xcode to assist me a little with implementing the delegate. To learn about using delegates in Objective-C I created this simple project.
http://www.smallsharptools.com/downloads/ObjC/Delegates.zip
It defines a Worker class which allows you to initialize the class with a delegate. When the work is done with the doWork method it looks for a method signature on the delegate to send a message back to it. It uses the following code.
if([[self delegate] respondsToSelector:#selector(workFinished:)]) {
NSString *msg = #"That's it? Easy!";
[[self delegate] workFinished:msg];
}
It looks for the workFinished: method to pass back a message. I declared this method signature as an optional interface with the following code in the header, Worker.h.
#protocol WorkerNotifications
#optional
- (void) workFinished: (NSString *) msg;
#end
You can see the rest of the project from the download for all of the details. But these 2 code snippets show how this delegation pattern works. But with the Twitter class I need to know the context of the method which started an asynchronous action which leads to a callback to a delegate method. If I call the sendUpdate method more than once from the calling class, how I am supposed to know the context of the callback?
Normally with a language like JavaScript, Java or C# I would create an inline closure or anonymous class which would have access to the starting context, but that is not possibly currently with Objective-C on the iPhone. I found that this question was already asked and answered on StackOverflow.
Anonymous delegate implementation in Objective-C?
So what I have done is skip the optional interface and instead passed in a selector which the Twitter class will call when the asynchronous action is completed. A call to start this action looks like...
CMTwitterEngine *engine = [[CMTwitterEngine alloc] initWithDelegate:self];
[engine setSendUpdateFinished:#selector(sendUpdateFinished:)];
[engine setSendUpdateFailed:#selector(sendUpdateFailed:)];
[engine setParsingSendUpdateFailed:#selector(parsingSendUpdateFailed:)];
[engine setUsername:TWITTER_USERNAME pass:TWITTER_PASSWORD];
[engine sendUpdate:statusUpdateText.text];
This code first initializes the engine reference with self as the delegate. To attach the callbacks I send in selectors which I originally had on the sendUpdate method signature but the method calls got pretty long. I opted to simply set properties of the selectors. This all works but I am not sure I like how this is working since it only partially solves my problem.
To complete this example, I finish the asynchronous work and eventually call a method internally which looks for the given selector and calls it if it is defined.
- (void)sendUpdateFinished:(NSDictionary *)dictionary {
if (self.sendUpdateFinished != nil) {
[self.delegate performSelector:self.sendUpdateFinished withObject:dictionary];
}
}
I can pass in the status message to send as a Twitter update but I still do not have the context of the originating call. What if I want to call sendUpdate more than once and the first asynchronous call is still running? And what if the second call finishes first? They will both have self as the delegate so I would have to either track the context somehow or pass them to a different selector to distinguish them, which also does not satisfy my needs. What happens if I have 3 or 4 or 5 asynchronous calls? I need to know which ones were sent successfully and when they are complete.
It appears the only way that I can do all this is to create a class which holds onto all of the properties needed for the context, have that class act as the delegate for the call to the asynchronous Twitter method and then report back to the parent class which is likely UIViewController. I would take this approach but I have not read about this approach or seen any sample code yet which does this.
What would you do? How would you handle multiple asynchronous calls going out which could end in a different order than going out and then process them with context upon completion?
I think your situation is a great place to use NSNotificationCenter
http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html
I have to second (or third) the previously posted answers in that NSNotificationCenter is probably what you're looking for here.
Essentially one typically uses notifications when there are potentially many delegates all of which need to do something in response to a single action or event that has occurred. Think of it as a one-to-many sort of delegation or an implementation of the observer pattern. The basic things to know are:
NSNotifications have a name that you define which is just an NSString. Notifications can be posted by name and objects register to receive notifications by name.
When a notification is posted a notificationSender object and/or userInfo dictionary can be provided. The notificationSender is the direct way of determining who posted a given notification when it is being handled by the receiver. The userInfo is an NSDictionary that can be used to provide additional context info along with the notification.
So, rather than forcing all of the workers to adopt to an informal protocol and messing around with reflection style calling-methods-at runtime you just register instances of the workers with NSNotificationCenter. Typically the registration with the NSNotificationCenter is done in an init method of each worker class. Instances of each type of worker are then typically set up as "freeze dried" objects in a NIB or can be programatically instantiated in the app delegate so that they get registered with the notification center early on in the app's life.
When the thing occurs you post a NSNotification to the NSNotificationCenter (which is essentially a singleton) and then everything else that has registered to receive that particular type of notification will have the method called that was specified to handle that type of notification. When done these methods can then call a common method back on the sender (obtained via NSNotification's object method) to tell the sender that they've completed their work.
Once each known worker has checked in the the common method on the sender can then go on to whatever post-worker-completion code is to be performed.
One thing to consider is using Notifications instead. Simplifies code, couples things less tightly.

iPhone Dev - Delegate or event?

In many situations, such as making the keyboard go away when the use clicks done, there are two options: set the text field's delegate to self, and adopt the UITextFieldDelegate protocol, and then use the method
- (BOOL)textFieldShouldReturn:(UITextField *)textField;
to resignFirstResponder and return YES. But you can also
addTarget:self
action:#selector(myMethod:)
forControlEvent:UIControlEventDidEndOnExit];
or something like that, using the did end on exit event, and then in the method, [sender resignFirstResponder]. So what is the best option in situations like these: the delegate, or the event?
The quick rule of thumb is that delegates are supposed to answer the question of "should I?" on behalf of the object they are a delegate for. Events, on the other hand, are broadcast afterward to let listeners know that something has happened.
In your case, while you could call [sender resignFirstResponder] in response to the event, you're mixing metaphors by doing this. Your delegate should have already made the decision to hide the keyboard (or not) and the event being broadcast is merely to let all the other components know that they keyboard hid.
If you are going to be paired with one other class, where the real type of that class may vary, then it makes a lot of sense to formalize that pairing into a protocol and a delegate arrangement.
If the information you want to send is targeted at a broader set of objects, then it starts to make more sense to use notifications - though now you have somewhat obscured what information is being passed by the notification as there's no central definition for what to expect.
Both are about an equal load to work with - with a delegate you have to set yourself and then remember to unset yourself before you are deallocated. You have to do the same thing with notifications, remember to start listening and then unsubscribe before you are deallocated.
Also, you should try as much as possible to make sure you send notifications out on the main thread as the notices get sent on the same thread they started from. Same goes for delegate methods, it's not very kind to call a delegate method from some other mystery thread!
The delegate makes your objects more reusable they are an adapter that lets any object interact with the defined behaviors of that object and use the object. I would say delegates should be adopted by the object responsible for keeping the state of and defining behavior to actions that will occur in the object that it is using. Events should be used for any other objects that are intersted in particular action that the object that has the protocol does (so objects not responsible for keeping the state of the object that defines the protocol).
For example: A view controller using a textfield will adopt its protocol to dismiss the keyboard and any other behaviors that can occur for a textfield, maybe another controller will do some animation when the keyboard is dismissed, so it will register to the textfield as an event in order to receieve the event of the keyboard being dismissed.

Delegation, some example of code? How object delegate to other

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.