Dravidian
Dravidian

Reputation: 9955

Programmatically delete a row from tableView from its customCell class with animation

GOAL

To delete a row from the TableView called from customTableViewCell

I have a tableView in my CustomTableViewController which deque's a customTableViewCell.

In that customTableViewCell class i have a UIButton Action which needs to change its buttonTitle when pressed, accordingly and delete the row itself if required.For this i am passing the indexPath of that cell to a globalVariable in that customTableViewCell class, which i use to delete my row accessing through the instance of CustomTableViewController.

CODE

Code for retrieving the database from firebase and struct is unnecessary ,just included for reference.

CustomTableViewController which has embed tableView in it:-

class FriendsListController: UIViewController , UITableViewDelegate , UITableViewDataSource,addingFriendDelegate{

  var profileFeed = [profileStruct]() //profileFeed is the an array of type struct, in which i am storing my retrieved database value's
   var customCellHandler = FriendsTableViewCell() 
  override func viewDidLoad() {

    super.viewDidLoad()
    listTableView.delegate = self
    listTableView.dataSource = self
     customCellHandler.delegate = self
    if friendListTable == true && profileFeed.isEmpty == true{

        FIRControllerHandle.retrievingForTheFriendListTableView { (userName, lctn, ID) in

            let temp = profileStruct.init(userName: userName, location: lctn, UID: ID)
            self.profileFeed.insert(temp, atIndex: 0)
            self.listTableView.reloadData()
            self.presentViews()

        }

    }else if friendListTable == false && profileFeed.isEmpty == true{

        print(profileFeed)
        print(profileFeed.isEmpty)

        FIRControllerHandle.retrievingForThePendingFriendRequests({ (userName, location, userId) in

            if self.profileFeed.isEmpty == true{

            let temp = profileStruct.init(userName: userName, location: location, UID: userId)
            self.profileFeed.insert(temp, atIndex: 0)
            self.listTableView.reloadData()
            self.presentViews()
            }
        })
      }
    }

    //Code for storing the data in a struct  is just for reference , trivial w.r.t context of my question

   }


   //addindFriendDelegate methods
  func deleteRowAtTheIndex(index: NSIndexPath){

        listTableView.deleteRowsAtIndexPaths([index], withRowAnimation: .Fade)

     }


//TableView delegate Functions.

func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    return 1
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return profileFeed.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = listTableView.dequeueReusableCellWithIdentifier("friendsCell") as! FriendsTableViewCell

    cell.userNameLabel.text = profileFeed[indexPath.row].profileName
    cell.userUID = profileFeed[indexPath.row].profileUserId
    cell.userName = profileFeed[indexPath.row].profileName
    cell.userLocationLabel.text = profileFeed[indexPath.row].profileLocation
    cell.currentUserName = currentuserName_initial
    cell.friendsListBool = friendListTable
    cell.cellIndexPath = indexPath   //Sending the indexPath of that row


    return cell

  }
}

customTableViewCell class which responds to buttons action:-

protocol addingFriendDelegate {
func deleteRowAtTheIndex(index: NSIndexPath)
    }

class FriendsTableViewCell: UITableViewCell {

var userName : String!
var userLocation : String!
var userUID : String!
var FIRControllerHandle : FIRController = FIRController() //I am using firebase as my backend and `FIRController` class handles all the firebase functions.
var delegate: addingFriendDelegate!
var friendsListBool : Bool = true // I am managing two tableViews datasource in one tableView , and `friendsListBool` tells me which node to retrieve from my database.
var currentUserName : String!
var cellIndexPath : NSIndexPath!
var listTableViewController : FriendsListController = FriendsListController() // Instance of viewController in which my tableView is embed


 @IBAction func addFriendsBtnAction(sender: CustomButton) {

    if friendsListBool{
    FIRControllerHandle.sendFriendRequest(userUID, completionBlock: {

           self.addFriendsBtn.setTitle("Sent", forState: .Normal) //Setting the title

           print(self.cellIndexPath.row) //Printing Fine
           self.listTableViewController.listTableView.deleteRowsAtIndexPaths([self.cellIndexPath], withRowAnimation: .Fade)


    })

    } else if !friendsListBool {

        FIRControllerHandle.accepFriendRequest(currentUserName, friendID: userUID, friendName : userName ,completionBlock: {

            self.addFriendsBtn.setTitle("Friends", forState: .Normal)



           })
       }
   }
}

WHAT HAVE I TRIED

self.listTableViewController.listTableView.deleteRowsAtIndexPaths([self.cellIndexPath], withRowAnimation: .Fade)

called in @IBAction func addFriendsBtnAction(sender: CustomButton) where listTableViewController is Instance of viewController in which my tableView is embed, and cellIndexPath indexPath of the row i want to delete

LINE OF ERROR

self.listTableViewController.listTableView.deleteRowsAtIndexPaths([self.cellIndexPath], withRowAnimation: .Fade)

Error:- fatal error: unexpectedly found nil while unwrapping an Optional value

(lldb)

PS:- I am not particularly inclined towards protocol-delegate method for this.I am looking for an alternative.

Upvotes: 3

Views: 894

Answers (1)

vadian
vadian

Reputation: 285290

Never initialize a view controller with the default initializer like FriendsListController().
It will create a brand new instance which is not the instance you expect in the view hierarchy.

An suitable alternative to protocol / delegate is a completion closure.

According to your latest code change the following:

  • Delete

    var customCellHandler = FriendsTableViewCell()
    var delegate: addingFriendDelegate!
    
  • Insert in cellForRowAtIndexPath

    cell.delegate = self
    
  • Insert in deleteRowAtTheIndex

    profileFeed.removeAtIndex(index.row)
    

Upvotes: 2

Related Questions