5

How do I go about this task? Basically, I will have an array of "seconds int" listed inside the UITableView. So how can I assign each "seconds int" to countdown to zero? The possible problems I'm seeing is the timers not being updated when the cell is not yet created. And how do I instantiate multiple independent NSTimers updating different ui elements? I'm quite lost here, so any suggestions is greatly appreciated. for visual purposes, I want to have something like this:

enter image description here

Qantas 94 Heavy
  • 15,750
  • 31
  • 68
  • 83
Diffy
  • 735
  • 1
  • 15
  • 34

2 Answers2

8

From the image, it looks like your model is a set of actions the user plans to take. I would arrange things this way:

1) MyAction is an NSObject with a name and a due date. MyAction implements something like this:

- (NSString *)timeRemainingString {
    NSDate *now = [NSDate date];
    NSTimeInterval secondsLeft = [self.dueDate timeIntervalSinceDate:now];
    // divide by 60, 3600, etc to make a pretty string with colons
    // just to get things going, for now, do something simple
    NSString *answer = [NSString stringWithFormat:@"seconds left = %f", secondsLeft];
    return answer;
}

2) StatusViewController keeps a handle to the model which is an NSArray of MyActions, it also has an NSTimer (just one) that tells it time is passing.

// schedule timer on viewDidAppear
// invalidate on viewWillDisappear

- (void)timerFired:(NSTimer *)timer {
    [self.tableView reloadData];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.model.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    MyAction *myAction = [self.model objectAtIndex:indexPath.row];

    // this can be a custom cell.  to get it working at first,
    // maybe start with the default properties of a UITableViewCell

    static NSString *CellIdentifier = @"Cell"; 
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    cell.textLabel.text = [myAction timeRemainingString];
    cell.detailTextLabel.text = [myAction name];
}
danh
  • 62,181
  • 10
  • 95
  • 136
  • thanks dude! how will this label (cell.textLabel.text = [myAction timeRemainingString];) be updated every tick? how do you call it every second? – Diffy Mar 29 '12 at 05:02
  • np. you'll set your view controller up to be the table's "delegate" and "datasource" (i should have mentioned that). when the ticks occur, you ask your table to reload it's data. the table takes care of the rest. it calls you back to ask how many cells it should load, and to configure each cell - both methods outlined in the code i provided. – danh Mar 29 '12 at 05:18
  • okay I got it working.. now I'm trying to change your - (NSString *)timeRemainingString method to - (NSString *)timeRemainingString:(NSTimeInterval)secondsRemaining so I can pass my array of seconds instead of a fixed value. How do I keep a reference of that value so it will deduct 1 second everytime the table is reloaded? – Diffy Mar 29 '12 at 05:45
  • You don't need to pass anything to it. The time remaining is the difference between it's due date and the current time. I don't thin you need an array of seconds either. "now" is advancing every second all by itself. – danh Mar 29 '12 at 05:52
  • If you'd prefer to stick with an array of seconds remaining (I don't think you should), then you would pick the member of that array using the indexPath.row. That single quantity of seconds left (for a particular action that is due) can be passed as a param to the method signature you suggested. – danh Mar 29 '12 at 05:57
  • right now, your code is working great. I added 60 seconds to dueDate and its counting down already(60 down to 0). The reason why I need an array of seconds is I will use this seconds as my dueDate coz each timer can have different values. Or is there a much better approach to this? – Diffy Mar 29 '12 at 06:10
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/9446/discussion-between-danh-and-diffy) – danh Mar 29 '12 at 06:16
  • hi, im just beginning with objC. But can you please tell me what kind of format Duedate is? somehow i can't get it to count down. i tried to add seconds to it but somehow thats not working. jaco – JsChoice Dec 07 '12 at 10:31
  • To implement the idea here, I think you should keep an array of NSDate. Run a single NSTimer. When it fires, refresh the table view. Each cell in the table presents the difference between the current time and the time stored in the array of dates at that cell's index. So seconds are not explicitly represented anywhere. – danh Dec 07 '12 at 15:52
0

To have fancy UI stuff in the table like that, you might want to subclass UITableViewCell and create a timer as a property in each. The cell can then own a delegate which responds to TimerWentOff and handles ringing of an alarm or a notification or whatnot. Each timer would update the label in it's cell.

Hope that helps a bit. If you have more specific questions, let me know.

Adam Shiemke
  • 3,734
  • 2
  • 22
  • 23
  • Thanks! Creating the custom cell is no problem, I already have that. So, this part "The cell can then own a delegate" this is the part that creates the countdown timer? Should I put the nstimers in an array and access one method to update the labels in my cell? – Diffy Mar 29 '12 at 03:47