2

I don't necessarily need code, but I would appreciate pretty specific steps/logic on how to handle my problem.

My initial view controller is a table view controller. It will show the individual timer value and display its counting down in the current cell. The timer value is retrieved from a separate regular view controller. This view controller contains a UIPicker and the timer value is calculated using the user-selected values from the picker.

I am having trouble with the logic for handling multiple timers in the tableviewcontroller. Each newly created cell should be assigned a new timer object that is created with the creation of that cell. This way, a specific cell uses the time value created with a specific UIPicker value. So far, I can only get it to where each cell uses the same timer value as the first cell that is created.

How do I tell a newly created cell located in my initial table view controller that it should only use the value created with its specific timer value selected by the user with the UIPicker located in the second view controller? How do I separate the timer values between cells?

Bista
  • 7,869
  • 3
  • 27
  • 55
Tiptech
  • 177
  • 1
  • 17

3 Answers3

2

You should never have a table view cell with logical implementations, so at the most, the interface of the cell should have a method called setTime, and you give it a String which it just assigns it to the label.

Now that this is cleared up, who should be doing the logic? I believe you can abstract the timer logic into their own objects, because it would be too much of a hassle for the table view controller to keep track of all the play/pause states, how much time has passed etc.

So the work that's left for table view controller is just to get the data (remaining time) from the timer objects, transform them into Strings (you might have formatting logic here that VCs should handle) then pass those strings to the cell.

The code would look like this:

var timerObject = timerObjectArray[rowNumber]
var timeRemaining: Date = timerObject.getTimeRemaining()
var timeString: String = convertToString(timeRemaining)
cell.setTimeString(timeString)

So now we try to figure out when/how to get the cells. As for when, that would be your choice, I think a NSTimer.scheduledTimerWithInterval could work (be careful of retain cycle)

Now in the method you pass to the schedule to be run every cycle, you should have code like this:

self.tableView.beginUpdates()
var visibleCells = self.tableView.visibleCells
for cell in visibleCells {
    var indexPath = self.tableView.indexPath(for: cell)
    var rowNumber = indexPath.row

    var timeRemainString = getTimeRemainingStringFor(row: rowNumber)
    cell.setTimeString(timeRemainString)
}
self.tableView.endUpdates()

Hope this helped! I probably missed something so just ask

Community
  • 1
  • 1
Jeff Woo
  • 86
  • 4
  • What would the getTimeRemainingStringFor() method look like? – Tiptech Feb 28 '17 at 05:50
  • It would just be something like the first codeblock, it would be an instance method, given the rowNumber, find the corresponding timer object and return a time string. – Jeff Woo Feb 28 '17 at 17:02
  • So in the method that I run every cycle (every second), when I set the cell text to rowNumber, each cell's text is correct. The first cell's text is row 1 or something like that, second cell's text is row 2, etc. So how do I set the text of the first cell to the string that's located at index 0 of the array, set the text of the second cell to the string that's at index 1 of the array of strings, and so forth. Something like this: cell.textLabel.text = string inside of array at element 0, then when a string is entered for element 1 in the array, the second cell text is that specific string. – Tiptech Mar 02 '17 at 15:35
  • From where we should call the timer method i.e. NSTimer.scheduledTimerWithInterval ? From cellForRowAt() Method or from somewhere else? – Krishna Meena Dec 15 '17 at 08:31
  • @JeffWoo could you possibly post more of the code or can you explain how tableview.beginupdates and end updates interacts with the normal tableview functions such as cellforrowatindexpath? Do they interact? or do you put it there? – bradford gray Sep 19 '18 at 15:17
1

I think your problem is maintaining state for each row data. Since table view reuses the cell, it becomes a problem. Save the state of the timers in an array in parent view controller. Set that value in every call of cellForRowAtIndex.

Amit Tandel
  • 883
  • 7
  • 16
0

Please use below instead of NSTimer.

Solution : 1

int64_t delayInSeconds = gameInterval; // Your Game Interval as mentioned above by you

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);

dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

    // Update your label here. 

});

Solution : 2

NSTimer.scheduledTimerWithTimeInterval(1, 
                    target: NSBlockOperation(block: {...}), 
                    selector: #selector(NSOperation.main), 
                    userInfo: nil, 
                    repeats: true)
Hitesh Surani
  • 12,733
  • 6
  • 54
  • 65