Objective c 如何在NSTimer循环期间刷新TableView单元格数据
免责声明:我是一个新的iOS转换,所以请随时告诉我,我的整个方法是错误的。我只要求你们解释一下原因——我的目标是学习(当然,也是解决这个问题) 大家好,我是iOS编程新手,在尝试解决这个问题好几个小时后,我的无知和经验不足让我感觉很好。希望我能在这里找到帮助 我有一个简单的TableView应用程序,我正在为一个正在开发的更大的应用程序开发一个沙箱。我现在尝试实现的功能是在TableView单元格(即Cell.detailTextLabel.text)中对字幕文本进行伪实时更新 为了让您更好地了解目标:我正在尝试这样做,用户可以点击TableView单元格,一个“秒表”样式的计时器开始在字幕文本中计数 但我不知道如何更新cell.detailTextLabel.text A)从我的计时器方法内部(它说tableView未声明)和B)以重复刷新单元格,让用户看到“活动”计时器 所以,这里有一些代码(所有这些现在都在RootViewController中。最终我想为计时器之类的函数创建单独的类,但我只想先让它们工作起来) 我还应该补充一点,我现在在这个类中有很多全局(“接口?”)变量。这使得实验更容易,但如果这可能导致一些问题,请让我知道。我还在学习如何来回传递对象/变量等Objective c 如何在NSTimer循环期间刷新TableView单元格数据,objective-c,cocoa-touch,xcode,ios,Objective C,Cocoa Touch,Xcode,Ios,免责声明:我是一个新的iOS转换,所以请随时告诉我,我的整个方法是错误的。我只要求你们解释一下原因——我的目标是学习(当然,也是解决这个问题) 大家好,我是iOS编程新手,在尝试解决这个问题好几个小时后,我的无知和经验不足让我感觉很好。希望我能在这里找到帮助 我有一个简单的TableView应用程序,我正在为一个正在开发的更大的应用程序开发一个沙箱。我现在尝试实现的功能是在TableView单元格(即Cell.detailTextLabel.text)中对字幕文本进行伪实时更新 为了让您更好地
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
self.runTimerFunctions;
}
然后是定时器功能(这些是接口变量):
数学和计算本身。结果生成格式为MM:SS.hh的单个字符串“liveTimer”,精确地向上“秒表”:
好的,liveTimer字符串是一个接口变量,所以我可以修改它并在整个过程中访问它(这可能不是实现这一点的方法,同样,我是一个noob,所以请在必要时纠正我)
在初始UITableViewCell创建位中,我使用liveTimer作为详细文本值,如下所示:
cell.textLabel.text = @"Name";
NSLog(@"liveTimer value is %@", liveTimer);
cell.detailTextLabel.text = liveTimer;
因此,从本质上讲,我现在拥有的东西,当用户按下列表项时,计时器开始在后台计数(我已经用NSLog确认它工作正常——如果我在targetMethod末尾提取liveTimer,它的格式正确,并且向上计数)
但我如何通过单元格文本的伪实时更新来反映这一点呢
当我将[tableView reloadData]放在任何我能放的地方时,它总是使程序崩溃(没有错误代码),但我不知道如何从targetMethod访问它(它告诉我在添加[tableView reloadData]时tableView未声明)
此外,[tableView reloadData]不断地使程序崩溃(没有错误消息),即使我试着通过实验将它放入,比如说,didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
self.runTimerFunctions;
[tableView reloadData];
基本上,我确信有一种简单的方法可以完成我想做的事情,但我对这门语言还太陌生,不知道如何去做。如果我试图在计时器循环中调用reloadData来重载系统,我不会感到惊讶。但话说回来,可能是其他原因
任何建议都将不胜感激。我正在尝试学习这里的语言,因此,尽管示例代码非常有用,但我同样对“学习如何钓鱼”感兴趣,因此我非常感谢解释为什么我所做的是错误的,以及更好的方法是什么,等等
提前感谢您的帮助;我期待参与论坛。首先,一个小错误
liveTimer=[NSString stringWithFormat:@“%@:%@.%@”,分钟字符串、秒字符串、百分字符串];
这可能就是您调用reload tableView时它崩溃的原因
你实际上想要:
要么:
self.liveTimer = [NSString stringWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString];
(如果已将liveTimer配置为属性而不仅仅是成员变量)
或
或
stringWithFormat:…
返回一个自动释放的字符串,这意味着它在运行循环的当前旋转结束时被释放。这将导致liveTimer基本上在函数完成后指向未定义的内存。使用self.liveTimer而不是liveTimer会导致合成的setter方法失败调用,而不是直接设置变量,这会导致对象在设置字符串时保留字符串(假设已将live timer属性设置为保留,如:@property(非原子,保留)NSString*liveTimer;
上面列出的另外两个选项都是先释放旧版本的字符串,然后保留新字符串,然后直接设置变量。第一个和最后一个选项中,您更喜欢哪一个或多或少是一个味道问题,第二个选项有点傻(它循环创建字符串,自动删除它,然后再次保留它。)
现在,谈谈你的问题
在-(void)targetMethod:(NSTimer*)timer
的末尾,您需要实际更新当前表格单元格(如果存在)。假设表格单元格存在于第0节的第0行:
-(void)targetMethod: (NSTimer *)theTimer {
// Everything you already had here, then...
NSIndexPath *cellIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
UITableViewCell *currentCell = [tableView cellForRowAtIndexPath:cellIndexPath];
// Returns the cell that's currently in the tableview at this location
currentCell.detailTextLabel.text = self.liveTimer;
}
如果当前单元格不存在(因为它已从屏幕上滚动),则cellForRowAtIndexPath:
将返回nil,而currentCell.detailtextlab.text=self.liveTimer;
将不做任何事情(即没有错误,只是字面上什么都不做)
编辑:
我刚刚注意到tableView不是对象成员变量之一
你是否有一个UITableViewController
可供使用?如果有,只要在当前使用tableView的任何地方使用tableViewControllerVariableName.tableView
。就是你的RootViewController(所有这些代码都在其中)UITableViewController?如果是,请在当前调用tableView的任何位置调用self.tableView
。如果不是,则在哪里分配tableView/tableViewController?可能会发布头文件
self.liveTimer = [NSString stringWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString];
[liveTimer release];
liveTimer = [[NSString stringWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString] retain];
[liveTimer release];
liveTimer = [[NSString alloc] initWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString];
-(void)targetMethod: (NSTimer *)theTimer {
// Everything you already had here, then...
NSIndexPath *cellIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
UITableViewCell *currentCell = [tableView cellForRowAtIndexPath:cellIndexPath];
// Returns the cell that's currently in the tableview at this location
currentCell.detailTextLabel.text = self.liveTimer;
}
liveTimer = [NSString stringWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString];
self.liveTimer = [NSString stringWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString];
[self setLiveTimer:[NSString stringWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString]];
-(void)setLiveTimer:(NSTimer *)newLiveTimer
{
[liveTimer release]; // This is the old value. It may be nil, which is fine. Calling methods on nil objects in objective-c is just be a noop, not a crash.
liveTimer = [newLiveTimer retain];
}
-(NSTimer *)liveTimer
{
return liveTimer;
}