Sent message or received message? - objective-c

As I known, [self setDate:...] mean self is receiver and setDate: is message. So which is the sender ?
I set a button with action (IBAction)buttonPressed:(id)sender. I understood that this button is the targer and buttonPressed is the action. So which is can be sender ?

1) As I known, [self setDate:...] mean self is receiver and setDate: is message. So which is the sender ?
The sender is the object—if any—that sent the message.
So which one is that?
You wrote the message in a statement.
You wrote that statement within a function, class method, or instance method.
If it was a function, then there is no object that was the sender.
If it was a class method, arguably the class is the sender (depending on how much you consider classes to be objects).
If it was an instance method, whichever object had that method called on it—i.e., received that message—is the sender of the setDate: message.
For example, if you sent your setDate: message from an instance method named buttonPressed: in an NSWindowController subclass, then your window controller—the instance (object) that received the buttonPressed: message—is the object that sent the setDate: message.
Of course, if the receiver of the message is self, then you are sending the message to yourself, so you are both the receiver and the sender.
2) I set a button with action (IBAction)buttonPressed:(id)sender. I understood that this button is the targer and buttonPressed is the action.
Nope! The button is not the target; the button has a target, which is another object. The target is the object that receives the action message.
Think of an archery target. The target doesn't send the arrow! It receives the arrow.
So which is can be sender ?
The object that is referred to by the sender variable generally is the object that sent the message.
Usually, it is a control (such as a button) or menu item: when pressed, the control or menu item sends its action message to its target, passing itself (the control or menu item) as the “sender”.
So your button would send a message to its target, the message being whichever one is set as the button's action, and because it's sending the message, it would pass itself as the sender.
The only reason to look at the sender at all is to examine the sender's tag or representedObject. An action method is about the only kind of method that may need to care at all about the sender (which is why it has this argument), and even then, usually not.

The sender is the object preforming the task....assuming your example (IBAction)buttonPressed:
If you are pressing a button, that button is doing the sending of whatever code follows. See my example
- (IBAction)pushButton:(id)sender {
UIButton *pushedButton = (UIButton *)sender;
[button setTitle:#"Press me to Send" forState:UIControlStateNormal];
}

1) Yes, self is the receiver of the message and setDate: is the message (the method call). There is no "sender". What do you mean by "sender" anyway?
2) In code, setting up the button to call the buttonPressed: method is done like this:
[someButton addTarget:someTarget action:#selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];
someTarget is typically self. The "target" is the object that has the "action" method. The method looks like:
- (void)buttonPressed:(UIButton *)button {
}
The "someButton" is the "sender" since it is the button that had the event.

Actually, In objective- c messaging system don't have any formal notion of "sender".
(IBAction)buttonPressed:(id)sender.
Here sender is just ordinary method argument ,not a part of objective c messaging system.Just a way argument is named in Appkit or UIKIt.
[self setDate:...]
here "self" is receiver and setDate: is message.
Please note : in ordinary speech "sending a message" implies three thing: sender,receiver and message.Where sender is function or block of code that contain message. But that analogy is not applicable for objective c.

Related

Obj-C IBAction (id)sender

I have an IBAction like:
- (IBAction)thisThing:(id)sender {
[self doSomething];
}
I would like do this (manually call the IBAction):
[self thisThing];
However I obviously need to do [self thisThing:...];. <- (what the heck goes after the colon?)
I'm not sure what (id)sender is supposed to be. How do call it manually without needing to click the button that it's tied to? I searched for anything about IBAction (id)sender and the results came up completely empty.
what the heck goes after the colon?
Well it depends on how you have written code inside the IBAction. Say for a calculator app, if all buttons are hooked up with the same IBAction then you would need sender (in this case NSButton) to identify which button got touched/clicked.
-(IBAction) buttonClicked:(id) sender {
// sender's identifier or Tag will let us know the number clicked here
[self doSomeThing];
}
But if you had IBActions for each and every button you would not need to be dependent on sender.
-(IBAction) firstButtonClicked:(id)sender;
-(IBAction) secondButtonClicked:(id)sender;
and so on ...
So in the first case if I want to programatically invoke the action I would pass the sender with appropriate attributes set to make sure the correct button got clicked. In second case just pass nil as it does not depend upon sender's value.
While popeye's comment answers your question, here's another perspective.
You have complete control over the action method. If you aren't using the sender parameter for anything in that method, then you do not have to supply it when calling it manually. By not supply it I mean pass nil as the value of the parameter.
Normally, it will contain a pointer to the control that is wired up to the action. If you did want to use if for something, they you would simply cast sender to the type of the control and do whatever with it.
- (IBAction)thisThing:(id)sender
In here,
- denotes the start of a instance method, whereas + means class(static) method.
( .. ) indicate return type. IBAction is actually void. Using IBAction instead of void tells that this method will be associated with UI(.nib) events.
thisThing is the name of the method, followed by parameter list.
In C view point, actual function names is something like thisThing:. That is, number of parameter modifies function name (external linkage).
If you meant to call thisThing: but write [self thisThing], you are calling different (not existing) method.
So, you must write :. What actual value to pass? One can decide this by looking at the method implementation.
If you have the IBOutlet of the button, you can pass that like [self thisThing:btn];
Or simply pass nil, [self thisThing:nil]; (if you are not using sender inside the IBAction)
- (IBAction)thisThing:(id)sender {
}
Is an event handler. That means that it is called when an event is sent by someone. A typical example of an event is a click on a button, it that case, the button sends the event (that means the button, a NSButton instance, is the sender).
Having the sender as a parameter is useful when you use the same event handler for events coming from different sources, e.g.
- (IBAction)buttonTapped:(id)sender {
if (sender == self.myButton1) {
//button 1 was tapped
}
else if (sender == self.myButton2) {
//button 2 was tapped
}
}
If this case, if you want to call the event handler manually, you just call
[self buttonTapped:self.myButton1];
If you don't use the sender parameter, then you can simply call
[self buttonTapped:nil];
However, the parameter is completely optional, so you can eliminate it:
- (IBAction)buttonTapped {
// ...
}
[self buttonTapped];
On a separate note, it's never good to call event handlers manually. Event handlers serve to handle events. If you need to perform the same action manually, separate it from the event handler, e.g.
- (IBAction)buttonTapped {
[self doSomething];
}
instead of calling [self buttonTapped], call [self doSomething]

Calling id selector from another selector

I have a selector declared with id sender, like this:
- (void)fbLoginClicked:(id)sender
{ }
I want to call it from another method like this:
[self fbLoginClicked];
But,I'm getting this error:
No visible selector 'fbLoginClicked'
How can I fix this?
The method signature requires that you pass a parameter (sender) to the method.
I'm assuming that this method is also an IBAction, hence why it requires a sender parameter.
To call this method through code you need to pass it a parameter, assuming that parameter is not used then you can simply call:
[self fbLoginClicked:nil];
If this method is not an IBAction and nothing is done with the sender parameter, then you could change the method signature to:
- (void)fbLoginClicked

calling button action function

just a quick question...say I have created a button and added some action to it:
-(IBAction)btnclicked:(id)sender {
//some code here
}
And now I wanna call it so i can do this:
[self btnclicked:self];
So my question is what role does the self after the btnclicked play? why will it be wrong to write it this way:
[self btnclicked:sender];
please help.
sender is type id, which can be any objective-c object (or nil). So you can pass whatever you like into the method and the compiler will be happy.
what you do inside that method may be excpeting a UIControl of some sort though, so if you pass in a UIView or NSString or anything else, there could be an unrecognized selector or some other crash. In other words, you can pass in what you like, as long as you know what you're doing.
for your question about it being wrong to pass in sender. I am guessing that is giving a compiler warning because sender is undefined in the context you are using it. sender is the variable name given to the argument inside the method, it is not a global variable or constant that can be passed around

Objective C - Core data and NSFetchedResultController?

So I have a fetched result controller that returns a list of objects.
I am trying to detect any changes to the object including changes to sub objects
Object has these properties (NSString myString, NSSNumber myNumber, Object2 myObject2)
so any changes to myString, and myNumber would cause the FetchedResultController to notify the delegate. But changes to myObject2 properties won't trigger the fetchedResultController to call the delegate.
Am i doing anything wrong? Am i suppose to manually let myObject know that it has to notify the fetchedResultController?
When you "change" myString and your NSFetchedResultsController (NSFRC) responds with its event, you need to realize what is actually occurring.
The NSFRC is using Key Value Observing to see your change. Now, assuming yourObj is your object that you mentioned above, and so when you type: yourObj.myString = #"New String" or [yourObj setMyString:#"New String"] any receivers observing that property (your NSFRC!) will be notified, because the setter is being called on your object.
Therefore, you are not receiving notifications on your "sub object" as you called it, because you are not accessing a property that is being observed by the NSFRC, rather a property of your sub object.
To trigger a notification of your sub object, you would need to call the sub object setter on your object. (ie. [myObj setObject2:obj2])
So here is the answer:
implement the following methods in child class (myObject2), and on every keyValue changes notify the owner class
- (void)willChangeValueForKey:(NSString *)key
{
[super willChangeValueForKey:key];
[self.myMainObject willChangeValueForKey:#"myObject2"];
}
- (void)didChangeValueForKey:(NSString *)key
{
[super didChangeValueForKey:key];
[self.myMainObject didChangeValueForKey:#"myObject2"];
}

What is passed as Sender on IBAction?

When I use the code -(IBAction) onClick1: (id) sender;, what will be passed as sender? I tried to use the sender as the object id and fails (I mean I used the code sender.tag and it didn't return).
I am sure that when I am using - (void)buttonTouched1:(UIButton *)sender; here the sender should act as an object id.
The sender is usually the object that will invoke the onClick1 message. For example if you have a button and you associate your -(IBAction)onClick1:(id)sender message with the "touch up inside" event of the button, then when you tap on the button, the object representing the button will be passed to onClick1:
-(IBAction)onClick1:(id)sender
{
UIButton *button = (UIButton*)sender;
NSLog(#"%#", button);
}
The sender variable is normally the object that sent the action message (this isn't exactly guaranteed — for example, you can send an action message yourself and pass anything you want — but that's how it's supposed to work).
You can't just write sender.tag in those methods because dot notation requires the object to have a static type so the compiler knows what message the property corresponds to. If you write [sender tag] instead, it will work.