Right overall picture, wrong implementation details in the first paragraph.
A "First Responder" in a NibFile is an Object …
No, actually, First Responder is nil
. Connecting a UI control (e.g., button) to First Responder in a nib is equivalent to [control setTarget:nil]
in code.
The reason for the First Responder fake-object in the nib window is that, in IB, you set target and action at the same time (ctrl-drag to target, choose action from pop-up menu). You can't set the action and leave the target unset, like you can in code, so to set it to nil
, you need to do so explicitly. That's what First Responder is for: it's a fake object representing nil
, so you can set the target and action the same way you would do when setting it to a specific real target.
Of course, you can't use this to set anything else to nil
, only views' targets. You can only use it to mean First Responder, not anything else.
So if the user klicks on an UI control, the Nib sets …
The nib doesn't do anything. It's just a freeze-dried collection of objects stored on disk. Even when you instantiate NSNib, all you're doing is defrosting some objects. It's the objects that do things.
In the case at hand, when you unarchive the control you connected to First Responder from the nib, its target is set to nil
(remember, that's what First Responder really is: a target of nil
). When a control's target is nil
, and the user clicks on it, it sends its action to whichever responder is the first responder at the time.
Your second and third paragraphs are correct.
I have a similar setup and becomeFirstResponder seems to work fine.
My custom cell:
@interface CustomCell : UITableViewCell
{
IBOutlet UITextField *costField;
}
And the delegate method from the controller class:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* CellTableIdentifer = @"CellTableIdentifer";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellTableIdentifer];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSUInteger row = [indexPath row];
ReceiptItem *receiptItem = [models objectAtIndex:row];
if (receiptItem == justAddedItem)
{
[cell.costField becomeFirstResponder];
justAddedItem = nil;
}
justAddedItem is set when the user clicks the button to add a new row to the table.
Best Answer
If your ultimate aim is just to resign the first responder, this should work:
[self.view endEditing:YES]