2016-03-01 42 views
0

我想在tableview中設置多個運行計時器值,以便用戶輕鬆檢查剩餘的時間並停止任何特定的計時器。如何在Tableview單元的iOS中顯示更新的多重NStimer值?

多個定時器完美啓動和更新值在NSLog顯示。 用戶爲特定配方設置NSTimer。 現在假設用戶在recipedetail中爲recipe1設置計時器,現在從該recipedetail返回。 然後再次在recipedetail中爲recipe2設置計時器,並從該recipedetail返回。 ,我想所有的定時器值顯示在UITableView。和在recipedetail屏幕上放置的tableview。

所以我的觀點是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 :"); 
     } 
    } 
+0

一旦你顯示的tableview,之後,如果你想改變裏面的tableview的價值觀,你必須更新tableview。否則它不會顯示新的值。 – Signare

+0

它顯示新的值,但是當我從任何配方的細節,並從下一次它來生成新的tableview對象,這就是爲什麼不顯示任何值。 –

+0

當你從任何配方的細節來回來,然後不要創建tableview的新對象。 – Signare

回答

1

我認爲ü需要驗光儀你的代碼,u需要每次都重新加載的tableview細胞時,配方定時器凝視特定配方

這是樣品演示ü可以用單獨的項目嘗試, 首先在Recipe .h文件中創建的NSObject象下面這樣Recipe類的子類,

#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,啓動定時器和回採定時器,你可以添加一些其他的功能,如果@end

你想..:)

ViewController.h file

#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 

,並詳細控制器與您的烹飪法詳情控制器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 

編輯源代碼u的共享 的細胞類型,我認爲,如果你想ü可以繼承的實現代碼如下細胞,並把計時器標籤所需的位置問題,

所以在你的代碼,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

+0

發生了什麼..?有什麼問題嗎 .. ? –

+0

我編輯的代碼檢查它 –

+1

其工作正常。 TYSM @Shan 當之無愧的100喜歡:) –

0

認沽UI相關的變化新的對象爲了更好的理解不顯示顯示如下代碼。你也可以把其他的UI相關的變化在Main_queue

dispatch_async(dispatch_get_main_queue(), ^{ 

      lbl.text=updated_timer; 

}); 
相關問題