Gold Challenge Question


#1

I followed the Gold Challenge literally, and created a BNREditDateViewController with a View created in a Xib which has a UIDatePicker. I created an init method initWithItem:, so that I could get access to the BNRItem.dateCreated property. This all worked. However, on reflection, I thought that it was a bad solution, because I am passing a pointer to the BNRItem to the view, providing an opportunity for unintended mischief. So, I went back and created an initWithDate initializer along with an NSDate *dateCreated property. However, this solution did not work – I suspect because of NSDate is immutable. My assumption is that assignment performs a copy, just like NSString. If this is correct, what is the canonical way of handling this? Would I store the address of the NSDate? (NSDate **) Or is there another mechanism to use?

thanks


#2

Stumbled into the same issue.
I believe your assumption is correct.

When you set the the NSDate* instance variable of the new view controller to be the date of the DatePicker, it creates a new instance (and therefore assigns the address of the new object to the instance variable. However, the address of the initial date object in BNRDetailViewController stays the same after (as you can see in the last line of my “debugging”.

I did some “debugging” via NSLog:

Result:
2014-07-21 19:33:29.987 Homepwner[14167:60b] Address of dateCreated instance var of BNRDetailViewController: 0x8c980d0
2014-07-21 19:33:33.893 Homepwner[14167:60b] (–Before–)Address of dateCreated instance variable item in DatePickerVC: 0x8c980d0
2014-07-21 19:33:33.893 Homepwner[14167:60b] (–After–)Address of dateCreated instance variable item in DatePickerVC: 0x8cf5260
2014-07-21 19:33:33.894 Homepwner[14167:60b] Address of dateCreated instance var of BNRDetailViewController: 0x8c980d0

BNRDateViewController.m:

- (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear]; NSLog(@"(--Before--)Address of dateCreated instance variable item in DatePickerVC: %p", self.dateCreated); self.dateCreated = self.datePicker.date; NSLog(@"(--After--)Address of dateCreated instance variable item in DatePickerVC: %p", self.dateCreated); }

BNRDetailViewController.m:

[code]- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear];
BNRItem *item = self.item;

self.nameField.text = item.itemName;
self.serialNumberField.text = item.serialNumber;
self.valueField.text = [NSString stringWithFormat:@"%d", item.valueInDollars];

static NSDateFormatter *dateFormatter = nil;
if (!dateFormatter) {
    dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateStyle = NSDateFormatterMediumStyle;
    dateFormatter.timeStyle = NSDateFormatterNoStyle;
}

NSLog(@"Address of dateCreated instance var of BNRDetailViewController: %p", self.item.dateCreated);
self.dateLabel.text = [dateFormatter stringFromDate:item.dateCreated];

}[/code]

I doubt passing a pointer-pointer is the “clean” way. All I could find on the Internet was this, which I don’t get (yet):

[quote] A better way would be to use a delegate on the date picker controller with a protocol that supports date picking.

Or, even better in this simple case, use a block based API: The date picker controller gets a completionBlock that the client controller would set before presenting the date picker.[/quote]

Source: http://stackoverflow.com/questions/16776364/how-to-pass-nsdate-as-a-pointer