How can I properly recognize what cells have had their subviews modified by the user?

Question!

I have a tableView and inside of it is custom cells. The whole thing syncs fine with NSUserDefaults, however there is a problem. These custom cells have textfields inside of them among other interactive subviews. When the user modifies the textfield of a cell, how can I determine the index of the cell so that I can properly match the data model to the tableView? I've tried assigning an index variable to each cell in the cellForIndexPath(...) method but this causes alot of potential bugs.

To get a sense for what my tableView looks like, just look at the Apple reminders app, which has custom cells which also contain interactive subviews.

Anyway, any alternative methods of determining this sort of data? There are tons of reminders apps that contain interactive subviews so there must be a better way!

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

        var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as GoalTableViewCell
        cell.goalTextField.text = goalsArray[indexPath.row].title
        cell.checkmarkImageView.visible = goalsArray[indexPath.row].checkmarked
        cell.blackLineView.visible = goalsArray[indexPath.row].checkmarked
        cell.enabled = goalsArray[indexPath.row].enabled
        cell.isLastCell = goalsArray[indexPath.row].isLastCell
        cell.priority = goalsArray[indexPath.row].priority as Priority
        cell.indexInTable = indexPath.row //this is how I assign the index of a cell. Problem is that cellForRowAtIndexPath is inconsistent.

        return cell
    }

Then to retrieve that data

func finishCreatingGoal(notification : NSNotification) { //this executes after a textfield resigns first responder status
        if (notification.name == "FinishCreatingGoal") {
            var userInfo = notification.userInfo!
            var text = userInfo["text"]! as String
            var index = userInfo["index"]! as Int //this index is pulled from the cell.indexInTable variable which is assigned in CellForIndexPath(...)

            goalsArray[index].title = text //this line crashes often after various manipulation of the tableView such as deleting rows and reordering them.
            saveGoals(goalsArray)

            let indexPath = NSIndexPath(forRow:index,inSection:0)
            self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
        }
    }


Answers
UITableView has a method indexPathForRowAtPoint: which you can use.

// textField is a subview of a cell

let point = tableView.convertPoint(CGPointZero, fromView: textField)
if let indexPath = tableView.indexPathForRowAtPoint(point) {
    let yourObject = dataSource[indexPath.row]
    // do something with it
}

Should be pretty self-explanatory.



A better option would be to have a Goal class (which is what I'm guessing you already have in goalsArray) that would contain all the information that the user stores. Then instead of setting all of the UI from the table view's delegate, just pass it a Goal object. I.e.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as GoalTableViewCell
    cell.goal = goalsArray[indexPath.row]
    return cell
}

Then in your GoalTableViewCell class you keep a reference to this goal as well as update the UI. Then when you want to check the index of the cell's Goal you can just search for it.

By : Guy Kogus


You could get the index of the cell via TouchEvents i.e. getting the point coordinates in the UITableview. Then extracting the index path from point location and then via which you could get the cell index. Here is the method that i used in my code to do the same.

- (void)checkButtonTapped:(id)sender event:(id)event
{
    NSSet *touches = [event allTouches];
    UITouch *touch = [touches anyObject];
    CGPoint currentTouchPosition = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];
    if (indexPath != nil)
    {
        NSLog(@"the cell index : %d", (int)indexPath.row);
    }
}

Update ---

This is how its done in Objective-C. I haven't still read about swift so i cannot translate it in swift.



This video can help you solving your question :)
By: admin