Saving changes to items


#1

On page 205 it has the following in the BNRDetailViewController…

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

// Clear first responder
[self.view endEditing:YES];

// "Save" changes to item
BNRItem *item = self.item;
item.itemName = self.nameField.text;
item.serialNumber = self.serialNumberField.text;
item.valueInDollars = [self.valueField.text intValue];

}[/code]
I have typed it in a dozen times, and when I try to practice this by creating a program–trying to mimic what I learned here–with a UITableViewController and a UIViewController nothing happens.

And I can see why nothing happens. It seems like an instance of BNRItem is created; but what is being done with it? As far as I can tell, nothing is. The book also doesn’t appear to explain how it’s being transferred either. Can anyone tell me why creating an instance of BNRItem is transferring data back to the UITableViewController subclass?


#2

Hello! Read through this post that has the same question: viewtopic.php?f=491&t=8366

After reading that, let me know if that answers your question. If not, let me know where the confusion still is.


#3

Hi Christian, I feel like you’re my personal tutor–you’ve been helping me out a lot! Thanks!

Your post makes sense. I was the OP of that thread, I had my question answered in it so I didn’t read what followed. If only I did, I wouldn’t have had to post a new topic. :wink:

I’ve been using protocols since I couldn’t get this to work. I have been jumping around re-reviewing chapters and I briefly remember a mention to the MVC-Store concept. Is this (Homepwner’s [BNRItemStore sharedStore]) what you would recommend as your default method of passing data between view controllers? Or would you typically use protocols?


#4

[quote=“slassen”]Hi Christian, I feel like you’re my personal tutor–you’ve been helping me out a lot! Thanks!

Your post makes sense. I was the OP of that thread, I had my question answered in it so I didn’t read what followed. If only I did, I wouldn’t have had to post a new topic. :wink:

I’ve been using protocols since I couldn’t get this to work. I have been jumping around re-reviewing chapters and I briefly remember a mention to the MVC-Store concept. Is this (Homepwner’s [BNRItemStore sharedStore]) what you would recommend as your default method of passing data between view controllers? Or would you typically use protocols?[/quote]

That’s why I hang around the forums! Glad to help. :slight_smile: And that topic morphed after your question was answered, so understandable that you didn’t see it. I’m actually glad that you started this post, as it’s more descriptive of the problem and might be easier for people with a similar problem to find.

First, what specifically could you not get to work? That is an important first step.

To answer your question specifically, I’ll give you the terrible “it depends”. In this circumstance, the code we have works well because the BNRItem that we are modifying already exists. So it is easy enough to give it to the BNRDetailViewController and say “hey, this BNRItem already exists, so when the user changes the values, change them on this specific BNRItem.”

Let me give you a (modified for anonymity) example of where I am using delegation (protocols) in an app I am currently working on for a client. The user is on Screen A and needs to choose a company, so there is a button that says “Choose Company”. When the user taps this, they are brought to Screen B where there is a list of companies. Screen B “tells” Screen A which company is picked by having Screen A be the delegate of Screen B. The delegate method is something like - (void)chooseCompanyController:(BNRChooseCompanyController *)controller didPickCompany:(BNRCompany *)company;

This works well because there are multiple companies. Firstly, Screen A doesn’t even know what companies exist (Screen B does a web service to get a list of companies), and secondly since there are multiple companies, Screen A of course doesn’t know which one the user will pick.

Hope that helps a little. If you give me examples of where you’d like to pass data around in your own applications, I can help you decide what a good format would be for doing so.


#5

I really haven’t been messing with anything too complicated, mostly just recycled ideas from your book so that I can practice without straying too far off topic. But as you can tell from certain things not working, I lean out the code in my simple programs so that I make a determination of what is actually doing what. (That’s why my program wouldn’t work using your viewWillDisappear method, because I scrapped the BNRItemStore.)

My program works, I just couldn’t get it to work using the viewWillDisappear, viewWillAppear methods that I mentioned where you create a new BNRItem. (pgs. 203-205)
Here is how I have it setup currently…

This is the first controller that pops up, a list of inventory items pop on the screen.-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { SELInventoryItemVC *vc = [[SELInventoryItemVC alloc] initWithNibName:@"SELInventoryItemVC" bundle:nil]; vc.item = self.inventoryItems[indexPath.row]; vc.index = indexPath.row; vc.delegate = self; [self.navigationController pushViewController:vc animated:YES]; }

And in my second controller when the user selects back it sends this to its delegate.-(void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear]; [self.view endEditing:YES]; SELInventoryItem *item = self.item; item.onHand = self.onHandTextField.text.intValue; [self.delegate sendBackEditedItem:item atIndex:self.index]; }

Where the first controller then executes the method required by the protocol.-(void)sendBackEditedItem:(SELInventoryItem *)item atIndex:(NSInteger)index { [self.inventoryItems replaceObjectAtIndex:index withObject:item]; }

So I guess this is where you let me know if, in this ‘depends’ case, I’m writing semi-efficiently or not efficiently at all. :wink:
Is this the way that you would implement transferring data between these two controllers?


#6

I don’t think that code actually has any effect on the behavior of the app - it seems unnecessary to me. You are replacing an item with literally itself (the same exact item). What are you not seeing work when you use the viewWillDisappear: code in the initial post? Can you also post your code for BNRItemsViewController -viewWillAppear:?

This picture from that other post might help to clarify: cl.ly/image/1M3y1B412721 Maybe? Let me know if that doesn’t make sense.


#7

I think we are both confused about what each other is talking about. I’ll clarify my end.

The code that I posted in my last post was from the program I wrote without a store, not Homepwner, therefore I’m not replacing an item with itself. It uses protocol-delegate just like your last post’s example.

As far as my original post… This is when I tried to lean out the code in Homepwner and not use BNRItemStore. I was trying to see how the item was saving without all of the additional code. However, I’m clear on how it works now after I viewed the linked post you provided. So I don’t believe I need any further elaboration on that.

So my last post was more about your comment at the very end of your last post of giving you examples of where I’d like to pass data around in my applications. Does that make sense?


#8

As yes, my apologies; I was indeed mixing things up. Yes, in your example, delegation is a fantastic approach. As long as that index never changes while editing (like if your app syncs with a web service) then I see no problem.

One thing that could be done better is the method signature of the delegate method. With delegation, the convention is “the object sending the delegate message is always the first argument to all of the delegate methods”. You can see this with UITableView and UITextField, as two examples that are used within the book. Let me give you a hypothetical use case to demonstrate why this is the case.

Imagine you have an iPad app that has TWO UITableViews on the screen at the same time, on the BNRAppStoreViewController (making this up, but iPad App Store does indeed look like this). The BNRAppStoreViewController would be the delegate of BOTH of the table views. So, each delegate method would have to answer for both table views. For example:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if ([tableView isEqual:self.paidAppsTableView] {
        return [self.paidApps count];
    }
    else { // if we are on the self.freeAppsTableView
        return [self.freeApps count];
    }
}

That’s an example as to why the object sending the message is that first argument. So in your example, I’d probably name the method -inventoryItemVC:didEditItem:atIndex:

Hope that helps!


#9

Ahhh, good advice! I wouldn’t have thought of that until much later; searching Google and forums frantically! :sunglasses: Thanks so much for the extra help.