tanvir
tanvir

Reputation: 317

Update or reload UITableView after completion of delete action on detail view

I have a uitableview that collects data from mysql through json. Then it has a detail view that has two action edit and delete. Edit works fine. Delete action deletes mysql data but problem is it does not update data from uitableview.

Here is screen shot and code

enter image description here

//Table View Controller

import UIKit

class TableViewController: UITableViewController {

    var storeList = [Store]()

    //var storeList:Store?


    override func viewDidLoad() {
        super.viewDidLoad()

        /*
        if let s = storeList
        {
            txtName.text = s.storeName
        }
*/


        // Uncomment the following line to preserve selection between presentations
         //self.clearsSelectionOnViewWillAppear = true

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem()

        self.loadRecords()
        self.tableView.reloadData()


    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.tableView.reloadData() // to reload selected cell

        //tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
    }








    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return storeList.count
    }


    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        //let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)

        // Configure the cell...

        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! StoreTVC



        let s = storeList[indexPath.row] as Store

        cell.lblName.text = s.storeName
        //cell.lblID.text = s.storeId


        return cell
    }

    // for swipe delete

    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == UITableViewCellEditingStyle.Delete {
            storeList.removeAtIndex(indexPath.row)
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
        }
    }




    /*
    // Override to support conditional editing of the table view.
    override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.
        return true
    }
    */

    /*
    // Override to support editing the table view.
    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            // Delete the row from the data source
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        } else if editingStyle == .Insert {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
        }    
    }
    */

    /*
    // Override to support rearranging the table view.
    override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {

    }
    */

    /*
    // Override to support conditional rearranging of the table view.
    override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return false if you do not want the item to be re-orderable.
        return true
    }
    */


    // 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.
        // Pass the selected object to the new view controller.

        /*

        if segue.identifier == "details"
        {

        //if let indexPath = tableView.indexPathForCell(sender as! UITableViewCell)

            if let indexPath = tableView.indexPathForSelectedRow
            {
                let s = storeList[indexPath.row] as Store

                let dvc = segue.destinationViewController as! ViewDetails

                dvc.store = s
            }

        }
*/

        if let indexPath = tableView.indexPathForCell(sender as! UITableViewCell)
        {
            let s = storeList[indexPath.row] as Store

            let dvc = segue.destinationViewController as! ViewDetails

            dvc.store = s
        }


    }


    func loadRecords()
    {
        //The address of the web service
        let urlString = "http://localhost/crud/read_for_table_view.php"

        // 1 - Create the session by getting the configuration and then crrating the session

        let config = NSURLSessionConfiguration.defaultSessionConfiguration()
        let session = NSURLSession(configuration: config, delegate: nil, delegateQueue: nil)

        //2 - Create the URL Object

        if let url = NSURL(string: urlString)
        {
            //3 - Create the request object

            let request = NSURLRequest(URL: url)

            //4 - execute the request

            let taskData = session.dataTaskWithRequest(request, completionHandler: {
                (data: NSData?, response:NSURLResponse?, error: NSError?) -> Void in

                //5 - Do something with the Data back

                if(data != nil)
                {
                    //we got some data back

                    print("\(data)")
                    /*
                    var  parseError:NSError?

                    let parsedStores = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &parseError) as! NSDictionary
                    */

                    do {
                        if let parsedStores = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
                            print("Json Data \n \(parsedStores)")

                            if let stores:AnyObject = parsedStores["result"]
                            {
                                self.parseJSON(stores)
                            }
                        }
                    } catch let error as NSError {
                        print(error.localizedDescription)
                    }



                }else
                {
                    //we got an error
                    print("Error getting stores :\(error!.localizedDescription)")
                }
            })

            taskData.resume()

        }

    }

    func parseJSON(jsonData:AnyObject)
    {
        if let storeData = jsonData as? [[NSObject:AnyObject]]
        {
            var store:Store

            //we loop through all the recors and everytime we create
            // an object of kind store and then add to the store list

            for s in storeData
            {
                store = Store()
                // this part is getting the values

                if let sId:AnyObject = s["id"]
                {
                    if let storeID = sId as? String
                    {
                        print("Store id = \(storeID)")
                        store.storeId = storeID
                    }
                }

                if let sn:AnyObject = s["name"]
                {
                    if let storeName = sn as? String
                    {
                        store.storeName = storeName

                    }
                }


                storeList += [store]
            }


            NSOperationQueue.mainQueue().addOperationWithBlock()
                {

                    self.tableView.reloadData()
            }
        }
    }


}

//Detail View

import UIKit

class TableViewController: UITableViewController {

    var storeList = [Store]()

    //var storeList:Store?


    override func viewDidLoad() {
        super.viewDidLoad()

        /*
        if let s = storeList
        {
            txtName.text = s.storeName
        }
*/


        // Uncomment the following line to preserve selection between presentations
         //self.clearsSelectionOnViewWillAppear = true

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem()

        self.loadRecords()
        self.tableView.reloadData()


    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.tableView.reloadData() // to reload selected cell

        //tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
    }








    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return storeList.count
    }


    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        //let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)

        // Configure the cell...

        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! StoreTVC



        let s = storeList[indexPath.row] as Store

        cell.lblName.text = s.storeName
        //cell.lblID.text = s.storeId


        return cell
    }

    // for swipe delete

    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == UITableViewCellEditingStyle.Delete {
            storeList.removeAtIndex(indexPath.row)
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
        }
    }




    /*
    // Override to support conditional editing of the table view.
    override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.
        return true
    }
    */

    /*
    // Override to support editing the table view.
    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            // Delete the row from the data source
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        } else if editingStyle == .Insert {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
        }    
    }
    */

    /*
    // Override to support rearranging the table view.
    override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {

    }
    */

    /*
    // Override to support conditional rearranging of the table view.
    override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return false if you do not want the item to be re-orderable.
        return true
    }
    */


    // 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.
        // Pass the selected object to the new view controller.

        /*

        if segue.identifier == "details"
        {

        //if let indexPath = tableView.indexPathForCell(sender as! UITableViewCell)

            if let indexPath = tableView.indexPathForSelectedRow
            {
                let s = storeList[indexPath.row] as Store

                let dvc = segue.destinationViewController as! ViewDetails

                dvc.store = s
            }

        }
*/

        if let indexPath = tableView.indexPathForCell(sender as! UITableViewCell)
        {
            let s = storeList[indexPath.row] as Store

            let dvc = segue.destinationViewController as! ViewDetails

            dvc.store = s
        }


    }


    func loadRecords()
    {
        //The address of the web service
        let urlString = "http://localhost/crud/read_for_table_view.php"

        // 1 - Create the session by getting the configuration and then crrating the session

        let config = NSURLSessionConfiguration.defaultSessionConfiguration()
        let session = NSURLSession(configuration: config, delegate: nil, delegateQueue: nil)

        //2 - Create the URL Object

        if let url = NSURL(string: urlString)
        {
            //3 - Create the request object

            let request = NSURLRequest(URL: url)

            //4 - execute the request

            let taskData = session.dataTaskWithRequest(request, completionHandler: {
                (data: NSData?, response:NSURLResponse?, error: NSError?) -> Void in

                //5 - Do something with the Data back

                if(data != nil)
                {
                    //we got some data back

                    print("\(data)")
                    /*
                    var  parseError:NSError?

                    let parsedStores = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &parseError) as! NSDictionary
                    */

                    do {
                        if let parsedStores = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
                            print("Json Data \n \(parsedStores)")

                            if let stores:AnyObject = parsedStores["result"]
                            {
                                self.parseJSON(stores)
                            }
                        }
                    } catch let error as NSError {
                        print(error.localizedDescription)
                    }



                }else
                {
                    //we got an error
                    print("Error getting stores :\(error!.localizedDescription)")
                }
            })

            taskData.resume()

        }

    }

    func parseJSON(jsonData:AnyObject)
    {
        if let storeData = jsonData as? [[NSObject:AnyObject]]
        {
            var store:Store

            //we loop through all the recors and everytime we create
            // an object of kind store and then add to the store list

            for s in storeData
            {
                store = Store()
                // this part is getting the values

                if let sId:AnyObject = s["id"]
                {
                    if let storeID = sId as? String
                    {
                        print("Store id = \(storeID)")
                        store.storeId = storeID
                    }
                }

                if let sn:AnyObject = s["name"]
                {
                    if let storeName = sn as? String
                    {
                        store.storeName = storeName

                    }
                }


                storeList += [store]
            }


            NSOperationQueue.mainQueue().addOperationWithBlock()
                {

                    self.tableView.reloadData()
            }
        }
    }


}

Can you please help ?

Upvotes: 19

Views: 5993

Answers (5)

Kazi Omar Faruk
Kazi Omar Faruk

Reputation: 117

Hope this code will help you.

func tableView(_ tableView: UITableView, commit editingStyle:    UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
       self.storeList.remove(at: indexPath.row)
       self.tableView.beginUpdates()
       self.tableView.deleteRows(at: [indexPath], with: .automatic)
       self.tableView.endUpdates() 
    }
}

Upvotes: 1

tanvir
tanvir

Reputation: 317

So I got answer.

here is the update

import UIKit

class TableViewController: UITableViewController {
    
    var storeList = [Store]()
    
    //var storeList:Store?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        /*
         if let s = storeList {
         txtName.text = s.storeName
         }
         */
        
        
        // Uncomment the following line to preserve selection between presentations
        //self.clearsSelectionOnViewWillAppear = true
        
        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem()
        
        self.loadRecords()
        self.tableView.reloadData()
    }
    
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.loadRecords() // to reload selected cell
        
        //tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // MARK: - Table view data source
    
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return storeList.count
    }
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        //let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
        
        // Configure the cell...
        
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! StoreTVC
        
        let s = storeList[indexPath.row] as Store
        
        cell.lblName.text = s.storeName
        //cell.lblID.text = s.storeId
        
        return cell
    }
    
    // for swipe delete
    
    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == UITableViewCellEditingStyle.Delete {
            storeList.removeAtIndex(indexPath.row)
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
        }
    }
    
    /*
     // Override to support conditional editing of the table view.
     override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
     // Return false if you do not want the specified item to be editable.
     return true
     }
     */
    
    /*
     // Override to support editing the table view.
     override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
     if editingStyle == .Delete {
     // Delete the row from the data source
     tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
     } else if editingStyle == .Insert {
     // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
     }
     }
     */
    
    /*
     // Override to support rearranging the table view.
     override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
     
     }
     */
    
    /*
     // Override to support conditional rearranging of the table view.
     override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
     // Return false if you do not want the item to be re-orderable.
     return true
     }
     */
    
    
    // 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.
        // Pass the selected object to the new view controller.
        
        /*
         
         if segue.identifier == "details" {
         
         //if let indexPath = tableView.indexPathForCell(sender as! UITableViewCell)
         
         if let indexPath = tableView.indexPathForSelectedRow {
         let s = storeList[indexPath.row] as Store
         
         let dvc = segue.destinationViewController as! ViewDetails
         
         dvc.store = s
         }
         
         }
         */
        
        if let indexPath = tableView.indexPathForCell(sender as! UITableViewCell) {
            let s = storeList[indexPath.row] as Store
            
            let dvc = segue.destinationViewController as! ViewDetails
            
            dvc.store = s
        }
    }
    
    func loadRecords() {
        //The address of the web service
        let urlString = "http://localhost/crud/read_for_table_view.php"
        
        // 1 - Create the session by getting the configuration and then crrating the session
        let config = NSURLSessionConfiguration.defaultSessionConfiguration()
        let session = NSURLSession(configuration: config, delegate: nil, delegateQueue: nil)
        
        //2 - Create the URL Object
        if let url = NSURL(string: urlString) {
            //3 - Create the request object
            let request = NSURLRequest(URL: url)
            
            //4 - execute the request
            let taskData = session.dataTaskWithRequest(request, completionHandler: {
                (data: NSData?, response:NSURLResponse?, error: NSError?) -> Void in
                
                //5 - Do something with the Data back
                
                if (data != nil) {
                    //we got some data back

                    print("\(data)")
                    /*
                     var  parseError:NSError?
                     
                     let parsedStores = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &parseError) as! NSDictionary
                     */
                    
                    do {
                        if let parsedStores = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
                            print("Json Data \n \(parsedStores)")
                            
                            if let stores:AnyObject = parsedStores["result"] {
                                self.parseJSON(stores)
                            }
                        }
                    } catch let error as NSError {
                        print(error.localizedDescription)
                    }
                } else {
                    //we got an error
                    print("Error getting stores :\(error!.localizedDescription)")
                }
            })
            
            taskData.resume()
        }
    }
    
    func parseJSON(jsonData:AnyObject) {
        storeList.removeAll()
        
        if let storeData = jsonData as? [[NSObject:AnyObject]] {
            var store:Store
            
            //we loop through all the recors and everytime we create
            // an object of kind store and then add to the store list
            for s in storeData {
                store = Store()
                // this part is getting the values
                
                if let sId:AnyObject = s["id"] {
                    if let storeID = sId as? String {
                        print("Store id = \(storeID)")
                        store.storeId = storeID
                    }
                }
                
                if let sn:AnyObject = s["name"] {
                    if let storeName = sn as? String {
                        store.storeName = storeName
                    }
                }
                
                storeList += [store]
            }
            
            NSOperationQueue.mainQueue().addOperationWithBlock() {
                self.tableView.reloadData()
            }
        }
    }
}

Upvotes: 7

tendai
tendai

Reputation: 1250

I know this is an old question, but my 2 cents are, if you want to reload your tableview, as long as when you're making any updates your storeList array in any way, you can just make use of didSet when declaring your storeList like this:

 var storeList: [Store] = []{
        didSet{
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        }
    }

With the above, you are saying, any time the storeList array has content removed, added or updated in any way, then on the main UI, reload the tableView, this way you don't need to manually make changes to your tableView, but changes to the storeList will trigger changes to the tableView

Upvotes: 2

Pranavan SP
Pranavan SP

Reputation: 1865

Here is the better solution for you rather than reload tableview in viewWillAppear. Approach using delegate.

On your Detail View Controller add.

weak var delegate : TableViewController!

Modify line of code on Table View Controller

if segue.identifier == "details"{
    if let indexPath = tableView.indexPathForSelectedRow{
      let s = storeList[indexPath.row] as Store
      let dvc = segue.destinationViewController as! ViewDetails
      dvc.store = s
      dvc.delegate = self
    }
}

When action complete on your Detail View or before dismiss details view. Execute below line in your Detail View.

self.delegate.tableView.reloadData()

Here I hope it's better way and best practice rather than your approach. Try it. :)

Upvotes: 5

Jigar Tarsariya
Jigar Tarsariya

Reputation: 3247

Try Below Code:

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == UITableViewCellEditingStyle.Delete {
        storeList.removeAtIndex(indexPath.row)
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
        self.loadRecords()
    }
}

Hope this will help you

Upvotes: 4

Related Questions