Screencast: https://www.youtube.com/watch?v=ZwehDwITEyI
This is really bizarre. The problem is to do with a label outlet sitting in a custom-designed table cell. That cell is of my CustomCell class. (actually called RA_FormCell if you watch the screencast).
CustomCell.h
@property (weak, nonatomic) IBOutlet UILabel *dayOutlet;
-(void)controller:(id<CustomCellDelegate>)controller didUpdateDay:(NSString *)theDay;
CustomCell.m
// Method is called by a view controller
// (which is itself a delegate of the CustomCell class,
// hence the identifier you see below)
-(void)controller:(id<CustomCellDelegate>)controller didUpdateDay:(NSString *)theDay;
{
NSLog(@"Method called") // confirms to me that method is called
self.dayOutlet.text = @"Goodmorning";
NSLog(@"%@", self.dayOutlet.text); // displays (null)
}
That final log does actually appear, so the method is definitely being called. I have discounted the following:
self.dayOutlet.text
is not written to elsewhere by any other method in the projectCustomCell
The problem was that the controller:didUpdateDay:
message was not sent to the correct instance of the cell class.
This occurred because I had not correctly assigned this cell to be the delegate for the view controller. For anyone interested, in my screencast at 3:50, you can see that I have the following in cellForRowAtIndexPath
:
RA_FormCell *cell = [tableView dequeueReusableCellWithIdentifier:self.formCellArray[indexPath.row] forIndexPath:indexPath];
self.delegate = cell
However, this means that self.delegate got continually overwritten as the table cells were generated. As a result, my controller:didUpdateDay
message was sent to the bottom cell of the table, and not the top one as I required.
The solution was simple - there's no need to have this second delegate at all. Instead, when the cell delegates to the view controller, it should pass self
into the message it delegates:
id<CustomCellDelegate> strongDelegate = self.delegate;
if ([strongDelegate respondsToSelector:@selector(customCell:didChangeDay1:)])
[strongDelegate customCell:self didChangeDay1:[sender value]];
Then, in the implementation of this method by the delegate, simply end it by changing the outlet directly:
-(void)customCell:(RA_FormCell *)customCell didChangeDay1:(double)value
// put logic here
customCell.dayOutlet.text = @"No problem!";
In general, there should rarely be a need for a two-way delegate structure. Keep it one way, from A
to B
, and just remember to have A
pass self
in any messages it sends to B
. That way, B
will know the object the message came from, and be able to communicate back to A
.
Thanks to Paulw11