This is the third in a series of articles about programming on the iPhone using SQLITE. If you have not yet done so, you should probably read part 1 and part 2 before attempting this article.
In the last article, we learned how to add new elements to the shopping list. During this session, we will learn how to delete and edit existing articles. The edit function will finally allow us to add notes, change the quantity needed, etc. from the application. Former versions required us to do that in the database.
Changes to Existing Code
We will start from where we left off, and discuss changes to the existing software, followed by the new software we need to write. We created an AddView in the last article, and we will modify that view for updates in this article. The modified view will allow the user to see all the database fields and make changes to them (except for the database item ID).
Root View Controller Changes
We will start out making a few changes to the Root Controller. We will be adding an Edit button and will need to hide the Add Button when the user is editing the existing entries. Eventually we will add a view and controller for the Item View, but let's start with some of the easy changes first.
Root View Controller Header
The only change we need to make at this point is to create a pointer to the Add button. We actually created this item in the previous version, but since we never needed to do anything else with it, we didn't bother to store its value. For this version, we need to remove the Add button when the user clicks on the Edit Button. This is because we don't want the user clicking the Add button while they are editing the list. So, when the user clicks on Edit, we will remove the Add button from the navigator bar, and replace it once the Done button is clicked to terminate Edit mode.
Root View Controller viewDidLoad Method
The changes to this method begin after the title is set. In the previous version, we added an Add Button but we didn't need to save a pointer to it since it was always present. However, once we add an Edit button, we will need to hide the Add Button whenever the user is in Edit mode. So we do the same thing we did before except that we assign the address of the Add button to a class pointer. We will set the right button item to nil when the user presses the Add button, and then restore the pointer when the user clicks on the Done button.
We also add the Edit button to the left side of the navigation bar. Notice the difference in adding the Add button and adding the Edit button. Since Edit is such a common functionality, adding Edit is much easier than any of the other navigation bar items. There is already an Edit button created for you; you only need to reference it. In fact, if you look at the comments in the generated method, it shows an assignment statement that adds an Edit button. The other thing we do here is to set the allowsSelectionDuringEditing property to true, indicating that the user will be able to select items during Edit mode. By default this property is false, which means that the user can only delete items but not make changes.
Root View Controller cellForRowAtIndexPath Method Changes
Once we get the new cell, we set the editingAccessoryType property to indicate that during Edit mode, the cells should have the disclosure indicator. In some older tutorials, you might notice the use of the accessoryTypeForRowWithIndexPath method to set the accessory indicator. This is an older method that has been deprecated and should not be used. In most cases, you will find that you only need to set a property to control the action and appearance that you want.
Root View Controller didSelectRowAtIndexPath Method Changes
This metho
d is called whenever the user selects a list item. In the previous version, we toggled the need status of the list item. By default, the user cannot select a cell when the user is in Edit mode, so this would not normally be a problem. However, now that we have configured the application so that the user can select an item during Edit mode, we need to test what mode we are in and execute the appropriate block of code. If we are not in Edit mode, we will execute what we have been doing. We will be implementing what needs to be done when we are in Edit mode a little later. We will just implement the Delete option for now. Deleting an item doesn't involve selecting the item, so this method won't be called if the user performs a delete. This method will only get called if the user toggles the need status during normal operation, or attempts to edit a field during Edit mode.
Root View Controller setEditing Method
This is a new method that we need now that we have added an Edit button. This method is called when either the Edit or Done button is clicked. The editing property is set to true if we are in editing mode; otherwise it is set to false. When the user enters edit mode, we have to make sure that the Add button is not available. Once the Done button is clicked, the Add button can be restored. This is why we created the class variable to save a pointer to the Add button. When the application enters edit mode, we set the right navigation bar button to nil; when the application leaves edit mode, we restore the Add button.
Root View Controller commitEditingStyle Method
This is the last method we need to implement at this point. It is called when the user requests that the data is updated following an editing operation. The item being edited is specified by the indexPath parameter. We need to determine if this is an Add or a Delete operation that is finishing.
If we are finishing a Delete, then the user has requested that the current entry be deleted. We must delete the entry from both the database as well as the items array that is used for the display. Although the item will be deleted from the array, we will call a method that will show the item being removed from the display.
If we are finishing an Add, then the item has already been added to the items array, and when the application returns from the AddView the viewWillAppear method will display the new information.
Build and Run
This is a good time to build your project and see if it is working. You should still be able to add new items like you did in the previous version. When you click on the Edit button, a delete button should appear at the far left of each entry and a disclosure indicator should appear at the right of each entry. If you click the delete button and confirm your decision, you should see the item you deleted get removed from the list.
If you select an entry while in Edit mode, you should see the item get selected and then deselected (turn dark and then turn light). Once you get this much of the application running, we will add the code necessary to make changes to the entries.
Edit Items
We are now ready to let the user make changes to items on the list. We already have a method that will update the database. We use that method when the user selects a list item to toggle between needed and not-needed. The view we want to use would look like the AddView, so we will modify the controller to handle either new items or existing items.
AddViewController Header Changes
Since the update method takes an indexPath as a parameter, we will add an NSIndexPath variable to the header and use that to indicate if the user is creating a new item or changing an existing one. If the path is nil, then it is a new item; otherwise it is an existing item.
We will need to allow other classes to set and get the path, so we declare it as a property and synthesize it in the source file. Since we will now need to access the existing list of items, we will add a pointer to the application delegate so that we can get the item for the selected entry. We will initialize that pointer when the class loads.
Changes to AddViewController Source Code
We will make a series of changes to the AddViewController to enable it to modify a selected entry in the shopping list. Start by adding a synthesize statement for the path property.
AddViewControllerViewDidLoad Changes
We need to modify the viewDidLoad method so that it obtains the pointer for the application delegate. We will need this pointer to access the items array that contains the entries for the shopping list.
We declared the application delegate pointer in the header, and here is where we initialize it. We simply request that the application return its delegate. We have used this code several times before, so it should be familiar to you by now.
saveClicked Changes
The next method we need to change is the saveClicked method. When we were only doing an add, we simply cleared the fields, let the user fill in the information, and when the Save button was clicked, we would insert a new item into the database and refresh the list. Now that we are also using this controller to update existing entries, we need to check for the type of save and act appropriately.
If the path variable is nil, then we are doing an add; otherwise we are doing an update, and the path variable is the location of the item that has been selected and should be updated. We either allocate a new item or obtain the selected one from the app delegate. We set the fields of the Item object to the content of the form.
If we are doing an update (path not nil), then we call the method we have been using to update the item. If we are doing an add, then we call the method we have been using to do an add, and we release the item object, just like before.
Regardless of the type of operation, we call readItems to refresh the list (we don't know what changes the user did, so if the name was changed, then the order might be affected.) We then dismiss the view, which will cause the RootController viewWillAppear method to reload the display.
AddViewController ViewWillAppear Changes
The next method we will change is the viewWillAppear method, which used to blank the fields of the form when we were only doing an add. We will still do that for an add, but for an update we will set the form with the contents of the selected Item object.
As with the previous method, we will use the value of the path variable to determine if we are doing an add or an update. Notice that for an add we will set the name field to the first responder, which causes the keyboard to appear ready to enter a name. We could do that for an update as well, but since the user could also be wanting to change the quantity or add a note, we let the user select the text field(s) they want to change.
RootViewController Changes
The only thing left to do is to go back to the RootViewController and make a few changes to perform the add/update.
addClicked Changes
Since we are reusing the AddViewController for both adding and updating, we will break out most of the logic into a new method and then call that method when either the Add button is clicked or when a row is selected when in the Edit mode.
If you compare the code in the new detailView method with what the addClicked method had, you will find them very similar. When doing an add, we set the path variable in the controller to nil, indicating a new entry. As you will see below, when doing an update, we will set it to the selected path.
didSelectRowAtIndexPath Changes
You might remember that earlier we made changes to the didSelectRowAtIndexPath method, but we left out one section where the user had selected a row during the Edit mode. If you built and ran the application when I suggested it earlier, you should have noticed that selecting a row while in Edit mode caused the row to blink, but nothing happened. We will now add one line of code which will allow the user to update the selected item. We call the detailView method we added earlier when we changed the addClicked method changes, but in this case we set the path variable to the selected indexPath.
Build and Run
That is all the changes for this version. You should be able to build and run the application. You can now add new items, change existing items, as well as delete items you no longer want.
As I have mentioned before, I have written this kind of application for every hand held I have ever owned. I tend to never delete items. I use the shopping list as a check list before I go shopping. If you only enter the things you are currently thinking of, then you will probably get home and realize that you had wanted to get some other things. Going through my entire list helps me consider each item and determine which ones I want to get.
In the next version of this application, we will add the ability to view a filtered list of only the items we need.
You can download the source code for this version from the download page for my personal web site.















