Is there any benefit of having (id)sender in IBAction - cocoa

When coding with cocoa I've noticed that it's not necessary to have sender parameter when defining IBAction, hence following action:
- (IBAction)showUserInfo:(id)sender;
can be declared as
- (IBAction)showUserInfo;
So I'm wondering if there is any other benefit besides having the button/menu item that sent the action? Only other situation I can think of is having few objects calling same IBAction. Anything else?

Doc says,
The sender parameter usually identifies the control sending the action message (although it can be another object substituted by the actual sender). The idea behind this is similar to a return address on a postcard. The target can query the sender for more information if it needs to.
The sender parameter helps if you want any data from it. For example, on UISegmentControl value change, as in #Mark Adams answer. So if you don't want any information from the sender, you can just omit it, as in your - (IBAction)showUserInfo; example.

It can be handy to use the sender argument when you're connecting the method to UI objects whose values can change and you may need to work with.
For instance if I wired up a method to a UISegmentedControl and set it's control event to UIControlEventValueChanged, I can use the object passed as the sender: argument to obtain it's selected segment index and then, based on the value, make a change in the UI.
-(IBAction)segmentedControlValueChanged:(id)sender
{
UISegmentedControl *control = (UISegmentedControl *)sender;
// Show or hide views depending on the selected index of the segmented control.
if (control.selectedSegmentIndex == 0)
someView.hidden = YES;
else
someView.hidden = NO;
}

Related

Change UILabel from appDelegate

I want to do some stuff from the appDelegate in Xcode. One of these things are to change a UILabel.
ViewController *viewController = [[UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:#"id"];
viewController.label.text = #"heeej";
I was told this would do the trick. Doesn't work. Label doesn't change. Does anyone know what the problem is?
There are several problems:
Don't do anything in the AppDelegate except for loading the window an the initial view controllers (if needed).
You are instantiating a new view controller in the first line. I assume you already have a view controller and you want to change the label in that view controller. Than you need a reference to that view controller and use this reference to send messages to it.
The label should not be a property of the view controller. You should try to follow the design pattern Model-View-Controller or the pattern Model-View-ViewModel. Ask you preferred search engine what those are if you don't know.
id as an identifier for anything in Objective-C is a bad idea because this is used as an object type.
Edit: You don't need a reference to change a property in the view controller. Use notifications to update the label. The system sends a notification with the name UIApplicationWillEnterForgroundNotification' (see [here][1]). Add the view controller as an observer to the[NSNotificationCenter defaultCenter]` for this name and react on the notification. Read the Apple documentation if you don't know what I am talking about.

Disabling a view in cappuccino

How can I disable a CPView? (so that the user can't interact with it while it's still visible)
It's useful for example when the user clicks on something that sends a request to the server and it should get disabled till the result comes back.
CPControls (as abstract subclass of CPView) contains a -setEnabled: method which most UI components inherit from.
http://cappuccino.org/learn/documentation/interface_c_p_control.html#a68d3dc4f2d0a4fad8699fd5982cddc2d
CPViews do not contain such a method, so in your CPView subclass you need to write your own method for enabling and disabling. Then override -mouseDown: and whatever else you need to (look at the docs for CPResponder for a complete list) and implement like so:
- (void)mouseDown:(id)sender
{
if ([self isEnabled])
[super mouseDown:sender];
}

What exactly is an NSTreeController's "arrangedObjects"?

I'm trying to bind an NSTreeController's "arrangedObjects" to a custom view's "managedContent" (so that it can show a custom outline, for instance). In the setter...
- (void)setManagedContent:(NSArray *)newManagedContentArray {
//code goes here
}
nothing ends up working since newManagedContentArray ("arrangedObjects") apparently isn't an NSArray (and therefore I can't addObject: etc. etc.) Instead it's showing up as an NSControllerTreeProxy. My question is, what exactly is "arrangedObjects" supposed to be? Am I supposed to bind to it? If so, how?
arrangedObjects isn't supposed to be an array for NSTreeController. It states this quite clearly in the documentation. What you do get is the proxy object you are seeing, which you can use the childNodes and descendantNodeAtIndexPath: method on to get your tree structure.

calling action obtained from button

I have following requirements:
Obtain action associated with NSButton using : - (SEL)action
Call the obtained action.
Can we perform 2nd pt. Generally we invoke an action like this- [self abc:nil] just thinking if we can invoke the method obtained from 2nd pt. in same way!
Try:
SEL actionSelector = [button action];
[self performSelector: actionSelector withObject:nil];
The action is just a selector—the name of a method. Any number of objects may have a method by that name, and even if only one class implements the method, you may have any number of instances of that class. So, you can't just call the name of a method, because that doesn't express what object will respond to it. You need an object that implements that method, and you need to send that message by that name to that object.
The most likely object you want to send the action message to is the button's target, so get that, the same way you got its action, and send the message to that object. Or, better yet, send the button a performClick: message; if you want to simulate the user clicking the button, that's the way to do that.

Cocoa-Bindings : Update NSObjectController manually?

In my little cocoa application I have bound the properties of a class to some text fields with help of a NSObjectController. The only problem I have so far: you always have to leave a text field before the NSObjectController updates the class with the current input.
This becomes a problem if the user doesn't leave a texfield and clicks on a Save/Submit Button right away. The class doesn't contain the current input. Always a bad thing.
I am looking for a way to avoid this. Like telling the NSObjectController to get the current input even if the user had exited the field. If this is possible I could put this command in the save-Method before saving and all would be fine.
Send a commitEditing message to your controller in the handler for the OK button. This will do what you're asking for. It's as simple as:
- (void)save:sender {
if (![self.myObjectController commitEditing]) {
// Handle error when object controller can't commit editing
}
// Other stuff
}
If you go to the text field's value binding and check the "Continuously Updates Value" option, that will cause the new value to be set on the model object each time the user changes it, i.e. once for each keystroke. That would ensure that the model had the correct value before closing the window, though it may be a bit overkill, depending on what the effects (if any) are of the value being set in your data model.

Resources