Josiah
Josiah

Reputation: 4783

Why would a property essentially disappear? Obj-C, Cocoa

I am quite stumped. I have an app with a class for storing item details. Called LEItem. Those items are stored in a store with a class labeled LEItemStore. I have a view with a table of all items. This works fine. If you tap on a row, it sends this message to LogbookFirstViewController.

 LogbookFirstViewController *logController = [[LogbookFirstViewController alloc] initForNewItem:NO];

    NSArray *items = [[LEItemStore sharedStore] allItems];
    LEItem *selectedItem = [items objectAtIndex:[indexPath row]];

    NSString *description = [selectedItem description];
    NSLog(@"%@", description);

    [logController setItem:selectedItem];
    [self dismissViewControllerAnimated:YES completion:nil];

That is in a TableView class. In the LogbookFirstViewController.m I have

-(void)setItem:(LEItem *)i{
    item = i;
    NSString *t = [item description];
    NSLog(@"In LogbookFirstViewController, returning %@", t);
}

This is where it gets odd. That works. It outputs the correct item, therefore I would think everything would be okay. But it's not. item is a class-level property, so it should stay, but it doesn't. In the same class, I have overrode this method.

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    //NSString *string = [item description];
    //NSLog(@"Item = %@", string);
    NSLog(@"View did Appear:animated");
    int glucoseValue = [item glucose];

    NSString *glucoseString = [NSString stringWithFormat:@"%d", glucoseValue];
    [glucoseField setText:glucoseString];

    int proteinValue = [item protein];
    NSString *proteinString = [NSString stringWithFormat:@"%d", proteinValue];
    [proteinField setText:proteinString];

    int carbsValuue = [item carbs];
    NSString *carbsString = [NSString stringWithFormat:@"%d", carbsValuue];
    [carbsField setText:carbsString];

    int insulinValue1 = [item insulin];
    NSString *insulin1String = [NSString stringWithFormat:@"%d", insulinValue1];
    [insulinField1 setText:insulin1String];

    int insulinValue2 = [item insulin2];
    NSString *insulinString2 = [NSString stringWithFormat:@"%d", insulinValue2];
    [insulinField2 setText:insulinString2];



    //NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
    //[dateFormatter setDateStyle:NSDateFormatterShortStyle];
    //[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
    //NSLog(@" The item was created on %@", [dateFormatter stringFromDate:[item dateCreated]]);
    //[dateButton setTitle:[dateFormatter stringFromDate:[item dateCreated]] forState:UIControlStateNormal];
    NSString *t = [item description];
    NSLog(@"Loading view... Returns: %@", t);
}

I know that it isn't the cleanest code, but the idea is the same. It uses exactly the same code as the setItem: method. However, this always returns (null). Why? The property appears to go missing at viewWillAppear.

Thanks.

EDIT

I solved the problem. As you can see, the checked answer below did give the right idea, here is what I did to solve it. The problem was that when I sent setItem: I used this code to get LogbookFirstViewController

 LogbookFirstViewController *logController = [[LogbookFirstViewController alloc] initForNewItem:NO];

As I know see, that created a new instance of LogbookFirstViewController, so therefore, the existing one did not change it's Item property, as properties are assigned to one instance. Therefore, I was only changing the value of Item for this "invisible" property.

To solve this, one must get the existing instance of the viewController. To do this I did the following:

In LogbookFirstViewController.h I added this property

@property (assign) LogbookFirstViewController *instance;

Then, synthesize instance in your .m and in the same placed I added this to viewDidLoad

- (void)viewDidLoad
{
    instance = self;
    ...

Then, in the other viewController, entriesViewController, I added this too the .h

@property (nonatomic, strong) LogbookFirstViewController *logController;

Synthesize it. Then, I just used my didSelectRowAtIndexPath the same way, just using the existing logController

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{


    NSArray *items = [[LEItemStore sharedStore] allItems];
    LEItem *selectedItem = [items objectAtIndex:[indexPath row]];

    NSString *description = [selectedItem description];
    NSLog(@"%@", description);
    NSLog(@"Setting controller: %@", logController);
    [logController setItem:selectedItem];
    [self dismissViewControllerAnimated:YES completion:nil];
}

Then it works!

Upvotes: 0

Views: 133

Answers (2)

Dave
Dave

Reputation: 1081

You should retain when assigning object to property without ARC:

-(void)setItem:(LEItem *)i{
    _item = [i retain];
    ...
}

If you use property with ARC, then write _item = i;:

-(void)setItem:(LEItem *)i{
    _item = i;
    ...
}

Upvotes: -1

Phillip Mills
Phillip Mills

Reputation: 31016

You have a line where you create the LogbookFirstViewController but you don't actually cause it to display anything (push or present). Since it's a local variable, it would appear that whatever instance of that controller is loading its view is not the same one that you initialize in the code you've shown.

You can verify this by adding a couple of NSLog lines, such as:

NSLog(@"Setting controller: %@", logController);  // Insert before existing line
[logController setItem:selectedItem];

...and...

[super viewWillAppear:animated];
NSLog(@"Viewing controller: %@", self);  // Insert after existing line

For things to work the way you want, those have to print the same address.

Upvotes: 2

Related Questions