ios - 如何在 Tableview 单元格 iOS 中显示更新的多个 NStimer 值?

标签 ios uitableview nstimer

我想在 tableview 中设置多个运行计时器值,以便用户轻松检查剩余时间并停止任何特定计时器。

Multiple Timer Start 和 updated value 完美地显示在 NSLog 中。 用户为特定配方设置 NSTimer。 现在假设用户在 recipedetail 中为 recipe1 设置了计时器,现在从那个 recipedetail 返回。 然后再次在 recipedetail 中为 recipe2 设置计时器,然后从该 recipedetail 返回。 我想在 UITableView 中显示所有计时器值。并将 tableview 放置在 recipedetail 屏幕上。

所以我的观点是 TimerUpdated 值显示在 NSLog 中但不显示在 tableview 中,因为每个 Recipedetails 屏幕都会生成 UITableView 的新对象所以值不会更新 perfactly

 -(IBAction)okBtn:(id)sender
    {
       [self countdownTimer];
    }
-(void)countdownTimer {

        [[NSUserDefaults standardUserDefaults]setObject:recipeboxId forKey:[NSString stringWithFormat:@"timer_%@",recipeboxId]];
        [[NSUserDefaults standardUserDefaults]synchronize];
        // set timer

        [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
        (theAppDelegate).timer = [NSTimer scheduledTimerWithTimeInterval:0.6f
                                                 target:self
                                               selector:@selector(updateCounter:)
                                               userInfo:recipeboxId
                                                repeats:YES];
        [(theAppDelegate).timer fire];
    //    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];//Timer run in background

        [self CreateLocalNotification];
    }


    -(void)calculateTimeFromPicker
    {
        NSString *hoursStr = [NSString stringWithFormat:@"%@",[hoursArray objectAtIndex:[self.picker_timer selectedRowInComponent:0]]];
        NSString *minsStr = [NSString stringWithFormat:@"%@",[minsArray objectAtIndex:[self.picker_timer selectedRowInComponent:1]]];
        NSString *secsStr = [NSString stringWithFormat:@"%@",[secsArray objectAtIndex:[self.picker_timer selectedRowInComponent:2]]];

        int hoursInt = [hoursStr intValue];
        int minsInt = [minsStr intValue];
        int secsInt = [secsStr intValue];

        interval = secsInt + (minsInt*60) + (hoursInt*3600);
        secondsLeft=interval;
    }
    - (void)updateCounter:(NSTimer *)theTimer {
        if(secondsLeft > 0 )
        {
            secondsLeft -- ;
            hours = secondsLeft / 3600;
            minutes = (secondsLeft % 3600) / 60;
            seconds = (secondsLeft %3600) % 60;

            [[NSUserDefaults standardUserDefaults]setInteger:secondsLeft forKey:[NSString stringWithFormat:@"secondsLeft_%@",recipeboxId]];
            [[NSUserDefaults standardUserDefaults]synchronize];

            NSLog(@"timer :%@",[NSString stringWithFormat:@"%02d:%02d:%02d", hours, minutes, seconds]);
            NSString *timer_updated_value=[NSString stringWithFormat:@"%02d:%02d:%02d", hours, minutes, seconds];
            [[NSUserDefaults standardUserDefaults]setObject:timer_updated_value forKey:[NSString stringWithFormat:@"updated_timer_%@",[(theAppDelegate).timer userInfo]]];
            [[NSUserDefaults standardUserDefaults]synchronize];
             recipeArr = [[(theAppDelegate).Timer_recipeIdArr reverseObjectEnumerator] allObjects];
            for (int section = 0; section < [recipeArr count]; section++)
                for (int section = 0; section < [recipeArr count]; section++)
                {

                    for (int row = 0; row < (int)[self.timerWindowTbl numberOfRowsInSection:section]; row++)
                    {

                        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];

                        UITableViewCell *cell = [self.timerWindowTbl cellForRowAtIndexPath:indexPath];

                                for(UILabel *lbl in [cell.contentView subviews])
                                {
                                    if([lbl isKindOfClass:[UILabel class]])
                                    {

                                        if(lbl.tag == 1)
                                        {
                                            NSString *timer_desc= [[NSUserDefaults standardUserDefaults]objectForKey:[NSString stringWithFormat:@"timerDescString_%@",recipeArr[indexPath.row]]];
                                            NSString *recipe_title=[[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"timerRecipeTitle_%@",recipeArr[indexPath.row]]];
                                            NSString *updated_timer=[[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"updated_timer_%@",recipeArr[indexPath.row]]];

                                            NSString *desc=[NSString stringWithFormat:@"%@\n'%@\' %@ %@.",recipe_title,timer_desc,NSLocalizedString(@"is done in",nil),updated_timer];
                                             lbl.text=updated_timer;
                                            [lbl setNeedsDisplay];

                                            NSLog(@"*******************************lbl.text:%@",lbl.text);
                                            lbl.numberOfLines=0;
                                            [lbl sizeToFit];
                                            for(UIButton *btn in [cell.contentView subviews])
                                            {
                                                if([btn isKindOfClass:[UIButton class]])
                                                {
                                                    if(btn.tag==2)
                                                    {
                                                        btn.titleLabel.text=[NSString stringWithFormat:@"%@",recipeArr[indexPath.row]];
                                                    }
                                                }
                                            }
                                            break;

                                        }
                                    }

                                }
                         }
                }
        }
        else
        {
            secondsLeft = hours = minutes = seconds = 0;
            [self TimerInvalidate];
            NSLog(@"Time out :");
        }
    }

最佳答案

我认为你需要重构你的代码,每次当食谱计时器盯着特定食谱时你需要重新加载 tableview 单元格

这是示例演示,您可以尝试使用单独的项目, 首先创建 NSObjectRecipe 类子类,如下所示,

Recipe.h 文件中

#import <Foundation/Foundation.h>
@class Recipe;
@protocol RecipeDelegate <NSObject> //we need to notify which recipe time changing
- (void)timerChangedInRecipe:(Recipe *)recipe;
@end


@interface Recipe : NSObject
@property (nonatomic, assign) NSInteger recipeboxId;
@property (nonatomic, strong) NSString *recipeName;
@property (nonatomic, strong) NSString *countTimer;

@property (nonatomic, assign) NSTimeInterval secondsLeft;
@property (nonatomic, assign) NSTimeInterval interval;

@property (nonatomic, assign) int hours;
@property (nonatomic, assign) int minutes;
@property (nonatomic, assign) int seconds;
@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, assign) id<RecipeDelegate>delegate;

- (id)initWithRecipieId:(NSInteger)recipeId recipeName:(NSString *)name;
- (void )currentTimerString;
- (void)startTimer; //use to start the timer
- (void)stopTimer;  //stop the timer

@结束

Recipe.m文件中

#import "Recipe.h"

@implementation Recipe
- (id)init
{
  self = [super init];
  if(self)
  {

  }
  return self;
}

- (id)initWithRecipieId:(NSInteger)recipeId recipeName:(NSString *)name
{
   self = [super init];
   if(self)
   {
      self.recipeboxId = recipeId;
      self.recipeName =  name;
   }
   return self;
}

- (void)currentTimerString //this is similar to your method updateCounter:
{
   self.secondsLeft -- ;
   if(self.secondsLeft > 0 )
   {
     _hours = (int)self.secondsLeft / 3600;
     _minutes = ((int)self.secondsLeft % 3600) / 60;
     _seconds = ((int)self.secondsLeft %3600) % 60;
     self.countTimer = [NSString stringWithFormat:@"%02d:%02d:%02d", self.hours, self.minutes, self.seconds];
      if([self.delegate respondsToSelector:@selector(timerChangedInRecipe:)]) 
         [self.delegate timerChangedInRecipe:self]; //notifying the tableview to reload the particular cell 
  }
  else
  {
     _hours = _minutes = _seconds = 0;
     [self stopTimer]; //timer finished stop the timer
  }
}

- (void)startTimer
 {
    if(_timer == nil)
      _timer =  [NSTimer scheduledTimerWithTimeInterval:0.6f target:self selector:@selector(currentTimerString) userInfo:nil repeats:YES];
   else
       [_timer fire];
 }

 - (void)stopTimer
 {
    if(_timer)
      [self.timer invalidate];
    self.timer = nil;
 }
 @end

我们创建了配方对象,这将处理定时器和通知到 tableview,启动定时器和停止定时器,如果你愿意,你可以添加一些其他功能.. :)

ViewController.h文件中

 #import <UIKit/UIKit.h>
 #import "Recipe.h" //import the recipe class
 @interface ViewController : UIViewController <UITableViewDataSource,UITableViewDelegate,RecipeDelegate>
 @property (weak, nonatomic) IBOutlet UITableView *timerWindowTbl;
 @property (nonatomic, strong) NSMutableArray *recipeArr; //array to hold the recipes
 @end

ViewController.m文件中

#import "ViewController.h"
#import "RecipeDetailViewController.h"

@interface ViewController ()

@end

@implementation ViewController

 - (void)viewDidLoad
 {
   [super viewDidLoad];
   // Do any additional setup after loading the view, typically from a nib.
   _recipeArr = [[NSMutableArray alloc] init];
   [self populateRecipe]; //i am simply creating the recipes hear for testing
 }

 - (void)viewWillAppear:(BOOL)animated
 {
   [super viewWillAppear:animated];
 }

 - (void)populateRecipe
 {
    for(NSInteger k = 0 ; k < 10 ; k++)
    {
      Recipe *recipe = [[Recipe alloc] initWithRecipieId:k recipe eName:[NSString stringWithFormat:@"recipe_%ld",(long)k]];

     [self.recipeArr addObject:recipe];
   }
}

 - (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
 }

 //just configure your tableview
 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
 {
    return 1;
 }


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

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"RECIPEE_CELL"];
   if(cell == nil)
   {
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"RECIPEE_CELL"];
   }
   Recipe *recipe = self.recipeArr[indexPath.row];
   recipe.delegate = self;
   cell.textLabel.text = recipe.recipeName;
   cell.detailTextLabel.text = recipe.countTimer;
   return cell;
 }

 //hear go to recipe detail controller and set timer
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
 {
    Recipe *selRecipe = self.recipeArr[indexPath.row];
    RecipeDetailViewController *recipeDetailController = [[RecipeDetailViewController alloc] initWithNibName:@"RecipeDetailViewController" bundle:nil];
   recipeDetailController.selectedRecipe = selRecipe;
   [self.navigationController pushViewController:recipeDetailController animated:YES];
 }

 //this is the delegate method from recipe class
 //this method is responsible for reloading the particular cell 
 - (void)timerChangedInRecipe:(Recipe *)recipe
 {
   NSInteger index = recipe.recipeboxId;
   NSIndexPath *rowPath = [NSIndexPath indexPathForRow:index inSection:0];
   [self.timerWindowTbl reloadRowsAtIndexPaths:@[rowPath] withRowAnimation:UITableViewRowAnimationNone]; 
 } 
 @end

详细 Controller 与您的食谱详细 Controller RecipeDetailViewController.h 文件相同

#import <UIKit/UIKit.h>
#import "Recipe.h"

@interface RecipeDetailViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIDatePicker *timePicker;
@property (weak, nonatomic) IBOutlet UIButton *okButton;
@property (weak, nonatomic) IBOutlet UILabel *timerLabel;
@property (nonatomic, strong) Recipe *selectedRecipe;  
- (IBAction)okBtn:(id)sender;
@end

RecipeDetailViewController.m 文件中,

 #import "RecipeDetailViewController.h"

 @interface RecipeDetailViewController ()

 @end

 @implementation RecipeDetailViewController

 - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    [_timePicker addTarget:self action:@selector(timerChanged:) forControlEvents:UIControlEventValueChanged]; //i am setting a sample picker
  }

  - (void)didReceiveMemoryWarning {
   [super didReceiveMemoryWarning];
   // Dispose of any resources that can be recreated.
 }

 - (void)timerChanged:(UIDatePicker *)datePickerView
 {
    NSTimeInterval duration = datePickerView.countDownDuration;
    int hours = (int)(duration/3600.0f);
    int minutes = ((int)duration - (hours * 3600))/60;
    int seconds = minutes/60;
    _selectedRecipe.interval    = seconds + (minutes*60) + (hours*3600);
    _selectedRecipe.secondsLeft =_selectedRecipe.interval;
    _timerLabel.text = [NSString stringWithFormat:@"%02d:%02d:%02d", hours, minutes, seconds];
   _selectedRecipe.interval = duration;
 }

 - (IBAction)okBtn:(id)sender //hear start the timer particular recipe
 {
   [_selectedRecipe startTimer];
 }
 @end

在你分享的源代码中编辑 我认为单元格类型中的问题,如果你愿意,你可以将 tableview 单元格子类化并将计时器标签放在所需位置,

所以在你的代码中,ViewController.m 文件替换下面的方法

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"RECIPEE_CELL"];
    if(cell == nil)
    {
       cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"RECIPEE_CELL"];
    }
    Recipe *recipe = self.recipeArr[indexPath.row];
    recipe.delegate = self;
    cell.textLabel.text = recipe.recipeName;
    cell.detailTextLabel.text = recipe.countTimer;
    NSLog(@"timer in cell :%@",cell.detailTextLabel.text);
    return cell;
 }

并在 RecipeDetailViewController.m 文件中替换,

 //no need to wait for value change 
- (IBAction)okBtn:(id)sender //hear start the timer particular recipe
 {
    NSTimeInterval duration = _timePicker.countDownDuration;
   _selectedRecipe.interval = duration;
   [_selectedRecipe startTimer];
 }

并且还在属性检查器中将 timePicker 模式更改为 Count Down Timer

您可以下载编辑 code hear

关于ios - 如何在 Tableview 单元格 iOS 中显示更新的多个 NStimer 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35715182/

相关文章:

ios - UITableViewCell 在滚动时显示错误的数据

ios - 如何从 Swift4 中的嵌套字典访问值?

ios - UIPageViewController自动滚动问题

ios - SWRevealViewController 无法工作,因为类型 'XX-ViewController' 的值没有成员 'revealViewController'

ios - 在不重新加载整个表格 View 的情况下更改 UITableView 的部分页眉/页脚标题

ios - FBFriendPickerViewController 中的自定义 UITable

iphone - UITableView 顶部和底部阴影

ios - 使用 RxSwift 创建一个 "reactive"API

objective-c - 在 Objective C 中创建默认值

ios - 该应用在 Payload/App Name.app 中引用了非公共(public)选择器