Wednesday, September 7, 2016

Brief Introduction to iOS Development - Part 19 - Edit Data Details and Unwind Segue

In this session, we will expand on the previous session and add editing function to the view controller that holds the details of the data item. In addition, we would like to introduce unwind segue. A feature that allow us to pass the edited details to the table view controller.

Start a new project with single view application as shown below.


Name the project as "Intro19"


Next, we need to delete the existing view controller and the view controller file. For details please refer to the previous session. The storyboard should be empty as per screen shot below.


Next, drag a table view controller to the storyboard.


The table view controller screen shot is shown below:


Next, create a new file for the table view controller as shown below:


Select Cocoa Touch Class under iOS Source.


Select UITableViewController as the subclass and use the name ContactList to be appended by TableViewController. Click Next and Create.


Select the tale view controller as shown below.


Under Identity Inspector, select the file we have just created as the class of this table view controller.


Next, go to the Attribute Inspector and make sure that the check box "Is Initial View Controller" is checked.


Then, we need to select the table view cell from the document outline.


At the Attribute Inspector, change the style from Custom to Basic and enter the reuse identifier with the name ContactListCell.


Notice that a label was inserted to the table view cell automatically since we are using basic style.


Next, we need to create the data file. Use the option Swift File as shown below.


Click Next and named the data file as ContactData.swift


For data structure use the following code:

// MARK: Data Structure
struct Contact {
    var name: String
    var phone: String
}

Screen shot shown below:


Below data structure we also include the collection of contacts using an array.


Below the variable, we also include the helper program to load sample contact data.

// MARK: Helper program to load sample data
func loadSampleContact() {
    
    let contact1 = Contact(name: "Name of Contact1", phone: "123")
    let contact2 = Contact(name: "Name of Contact2", phone: "456")
    let contact3 = Contact(name: "Name of Contact3", phone: "789")
    
    contactList += [contact1, contact2, contact3]
    
}



Previously, we used to put all these data related code in the view controller. We think that it would be better to suit the MVC model if we separate the data related code from the view controller.  The complete code for the data swift file is shown below:

// MARK: Data Structure
struct Contact {
    var name: String
    var phone: String
}

// MARK: Data Variables
var contactList = [Contact]()


// MARK: Helper program to load sample data
func loadSampleContact() {
    
    let contact1 = Contact(name: "Name of Contact1", phone: "123")
    let contact2 = Contact(name: "Name of Contact2", phone: "456")
    let contact3 = Contact(name: "Name of Contact3", phone: "789")
    
    contactList += [contact1, contact2, contact3]
    
}

Screen shot shown below:


Next, we need to include the load sample helper program under viewDidLoad()


As usual, we need to configure the data source in the table view controller. These include the number of section as shown below.


We also need to supply number of rows.


And we also need to configure each cell. Since we are using basic style, we need to add the contact name to the label in the table view cell.


As usual, we have only one section.


The number of rows is the array count of contactList.


To configure the cell, we pass the name of each member of contactList to the label.


Next, select the table view controller by clicking on the first yellow button as shown below.


Next we embed the tale view controller with a navigation controller. We do this by selecting the table view controller, select editor > Embed In > Navigation Controller as shown below


The navigation bar will appear on top of the table view controller. At the middle, double click and enter the title of the table as shown below.


If we run the app now, it should display all the sample contact in a list.


This completes part 1 of the app where we install and configure a table view controller. The next step is to include a view controller to display the details of a contact.

From the object library, select a view controller and drag to any empty space on the storyboard.


The view controller might overlapped with the table view controller, we need to drag the view controller to the side and arrange the view controller to be aside with the table view controller.


Next, select table view cell as shown below:


Now, we need to click the blue bar and press control + drag from the table view cell to the view controller. Once we release the mouse click, a segue selection box, similar to the one below, will appear.


Select Show as the preferred segue type. Next, we will drag 2 labels and 2 textfields to the view controller.


To arrange the first label, the auto layout is shown below.


The auto layout for the first textfield is shown below.


The auto layout for second label is shown below


The auto layout for the second textfield as shown below.


Next we need to configure the first textfield. The settings are shown below:


The settings of the second textfield is shown below


Next, we need to create a view controller file for this view controller. As usual, select Cocoa Touch Class as shown below.


Select UIViewController as the subclass and insert the name ContactDetail in front of the ViewController


Next, we select the view controller as shown below.

At the Identity Inspector, change the class to the name of the file we have just created. This way we link the file to this view controller.


Next, we will link the textfield outlet to the view controller file. Switch to assistant editor mode and control + drag the first textfield to the view controller. The connection detail is shown below:


The connection for the second textfield is shown below


The resulting code should be same as the screen shot below


Next, we need to add an optional Contact variable to hold the details of a contact. The variable is shown below.


The code for the properties section is shown below:


Next, we need to switch to the table view controller. Go to the bottom of the template and un-comment the template marked as Navigation.


When user select the table view cell, which trigger the segue to the detail view controller, this section of code will activate before the transition to the next view controller. We will take this opportunity to pass the details of the selected cell to the view controller.

The code is as follows:

    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        // Get the new view controller using segue.destinationViewController.
        let editContactDetailViewController = segue.destinationViewController as! ContactDetailViewController
        
        // Pass the selected object to the new view controller.
        if let selectedCell = sender as? UITableViewCell {
            
            let selectedIndexPath = tableView.indexPathForCell(selectedCell)!
            let selectedContact = contactList[selectedIndexPath.row]
            editContactDetailViewController.detailContact = selectedContact
            
        }   
    }

As explained earlier, first we must assign a destination view controller. Next we use optional check to make sure that the sender is from table view cell. Once we confirm the sender, we will use method from table view class to extract the index path. Then we use the index path to call the correct contact details from the array. Finally, we pass the details to the optional contact details (variable: detailContact) contain in the destination view controller.

Screen shot below:


Next, we need to switch to the detail view controller. Under viewDidLoad, we will check if there is any data stored in the variable detailContact, if yes, we will pass the data to the respective textfield.


        // Check if there is any contact pass from the table view 
        if let gotContactToEdit = detailContact {
            
            contactNameTextField.text = gotContactToEdit.name
            contactPhoneTextField.text = gotContactToEdit.phone
        }


Now, we can run the program to check if the detail view controller display the data details correctly.


When we select one of the sample contact, the details is shown as per screen shot below:


Click on the title "Contact List" on the navigation bar to return to the table view. Now we need to configure the navigation bar on the detail view controller. As the detail view controller only make use of the left most section of the navigation bar, we can add a title and also make use of the right portion of navigation bar. To so do, find a Navigation item as shown below.


Drag the navigation item and drop it to the navigation bar.


Now, we have an option to enter the title. Name the title as "Edit Contact"


Next, find a Bar Button Item as shown below.


Drag it to the top right corner of the detail view controller.


Select the bar button and on the Attribute Inspector, change the system item to Save.


The resulting effect of the navigation bar is shown below:



Now, we need to link this save button to the detail view controller as an outlet as shown below.


The resulting code for the properties section is shown below


Next, go to the end of the template code and un-comment the template marked as Navigation. This is in preparation when user want to segue back to the table view controller.


The preparation code is as follows:


    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        
        if sender === saveButton {
            
            var myName: String
            
            let nameCheck = contactNameTextField.text ?? ""
            
            if nameCheck.isEmpty {
                
                myName = "No Name"
                
            } else {
                
                myName = nameCheck
                
            }
            
            
            let myPhone = contactPhoneTextField.text ?? ""
            
            detailContact = Contact(name: myName, phone: myPhone)
            
        }
        
        
    }


In this section of the code, first we check if the sender is from the save button. We only carry on if the sender is from the save button. Next we check if the textfield is empty if it is, then we will supply a "No Name" to the name field. If the testing is alright, then we will pass the contact details to the optional variable detailContact.

Screen shot below:


Now, we need to switch back to the table view controller. Add the following code:


@IBAction func editContactUnwindToContactList(segue: UIStoryboardSegue) {

        
}
    

This is a function program that will trigger when user unwind or reverse their segue back to the original view controller.


Inside code, we use optional to make sure that the source view controller is indeed from detail view controller.


Inside the code, we use tableview to search for the selected index path. Then we transfer the edited details from the source view controller to the array. Finally, we reload the table view cell for the selected row to refresh the edited data.

The full code for this function is shown below:

@IBAction func editContactUnwindToContactList(segue: UIStoryboardSegue) {
        
        if let editContactViewController = segue.sourceViewController as? ContactDetailViewController {
            
            let selectedIndexPath = tableView.indexPathForSelectedRow!
            contactList[selectedIndexPath.row] = editContactViewController.detailContact!
            tableView.reloadRowsAtIndexPaths([selectedIndexPath], withRowAnimation: .None)
            
            
        }
        
    } 

Screen shot shown below:


To link the previous code, we need to control + drag from the save button to the exit button as shown below. A list of function will appear, select the function that we have just configured.

Finally, we can test the app by running the app again. Select any sample.


Details is shown using the detail view controller. Try to change something by clicking on the textfield and the appropriate keyboard will appear.


Change something on the Phone textfield and press Save.


The system will return back to the table view controller. Select the same sample again.


The edited information will appear on the details.



A copy of this project can be found at Github at https://github.com/SwiftiCode/Intro19

*** End ***

No comments:

Post a Comment