我想在tableview中设置多个运行计时器值,以便用户轻松检查剩余时间并停止任何特定计时器。
多个计时器启动和更新值完全显示在NSLog
中。
用户为特定配方设置NSTimer
。
现在假设用户在recipedetail中为recipe1设置计时器,现在从该recipedetail返回。
然后再次在recipedetail中为recipe2设置计时器,然后从该recipedetail返回。
我想在UITableView
中显示所有计时器值。并且tableview放在recipedetail屏幕上。
所以我的观点是NSLog
中的TimerUpdated值显示但不显示在tableview中,因为每个Recipedetails屏幕都会生成UITableView
的新对象,因此值不会更新
-(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 :(得分:1)
我认为您需要对代码进行折射,每当配方计时器盯着特定食谱时,您需要重新加载tableview单元格
这是示例演示,您可以尝试使用单独的项目,
首先创建一个Recipe
类NSObject
的子类,如下所示,
Recipe .h
@end
<{1>}文件中的
#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
我们创建了配方对象,这将处理计时器和通知到tableview,启动计时器并停止计时器,你可以添加一些其他功能,如果你想...:)
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
<{1>}文件中的
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
在源代码中编辑你是共享的 我认为,单元格类型中的问题,如果你想要你可以子类化tableview单元格并将计时器标签放在所需的位置,
因此,在您的代码中,#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
文件替换
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
您可以下载已修改 code hear
答案 1 :(得分:0)
在主队列中放置与UI相关的更改,以便更好地理解下面给出的代码。您还可以在Main_queue中添加其他与UI相关的更改
dispatch_async(dispatch_get_main_queue(), ^{
lbl.text=updated_timer;
});