Reputation: 9955
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
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