【问题标题】:one timer per detail view controller每个细节视图控制器一个计时器
【发布时间】:2013-07-28 03:18:52
【问题描述】:

我有一个带有表格视图属性的视图控制器和一个通过导航栏连接到表格视图中每个单元格的详细视图控制器。在详细视图控制器中是一个倒数计时器,在用户创建任务时指定了一个时间间隔。我试图让每个单元格(或任务)都有一个独特的细节视图控制器。我正在使用核心数据。这就是我现在拥有的:

-(void)tableView:(UITableView *)tableView 
    didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    if (!self.detailViewController) {
        self.detailViewController = 
            [[DetailViewController alloc] initWithNibName:@"DetailViewController" 
                                                   bundle:nil];
    }
        Tasks *task = [[self fetchedResultsController] objectAtIndexPath:indexPath];
        self.detailViewController.testTask = task;
        [[self navigationController] pushViewController:self.detailViewController 
                                               animated:YES];

}

DetailViewController.m

@interface DetailViewController : UIViewController <UIAlertViewDelegate>
@property (weak, nonatomic) IBOutlet UILabel *timeLeft;
@property (weak, nonatomic) IBOutlet UILabel *timerLabel;
@property (nonatomic, strong) Tasks *testTask;
@end

我觉得这是实现细节视图控制器的正确方法,因为它最大限度地减少了需要创建的内存量,但它并不真正适合我的需求。当前,当用户点击一个单元格,然后点击返回,然后点击另一个单元格时,只会加载第一个单元格的属性。此外,如果我要删除一个单元格,则无法使用此方法使其计时器(我认为)无效。有什么建议吗?

---编辑--- 我想我应该问的问题是:我应该如何使每个详细视图都有一个递减标签(从计时器获取其信息)?

【问题讨论】:

  • 是否需要同时运行多个定时器?
  • 是的。如果用户启动计时器,即使他们在详细视图控制器上点击,它也需要运行,直到时间结束或用户停止计时器。
  • 我会尝试从您的主视图控制器管理您的计时器,而不是为每个细节设置一个计时器。
  • 嗯..为什么以及如何做到这一点?
  • 当按下后退按钮时,详细视图控制器应该会耗尽内存,这是您使计时器无效的问题。此外,如果用户有多个任务同时进行,他们可能希望同时查看两个任务的进度。 How - 我将在单元格中包含任务描述、开始/停止按钮和 timeLeft 标签。让 1 个计时器进入您的主程序并存储所有已启动的单元格的数组 - 每秒钟都会从您的计时器中增加它们的标签。

标签: iphone ios objective-c uiviewcontroller timer


【解决方案1】:

您最好的解决方案是在这种情况下正确遵循 MVC。在您的情况下,您正在为您正在创建的每个 detailViewController 存储数据(例如任务和倒数计时器/间隔等)。在 rdelmar 的answer 中,他建议您将所有视图控制器存储在 mutableArray 中。我不同意这两种方法,因为当您关闭视图控制器(正如您自己所见)和在 rdelmar 的情况下,您将视图控制器(连同它们引用的数据)存储在可变数组中时,您的方法会出现内存问题。很浪费。

这样想..您想在一个地方跟踪数据(这不受现在显示的视图的影响..它可能是 detailVC 1 或 100 或带有 tableView 的 VC 或任何一个)同时,您希望一次分配 一个 detailVC,以显示数据源告诉它要显示的任何内容。这样你就可以扩展你的应用程序(想象一下如果你的表中有数百个索引会发生什么......你会存储数百个视图控制器吗?非常昂贵且冗余)。

所以只需创建一个 singelton .. singelton 将有一个 mutableArray 存储与每个点击的表索引相关的计时器等等.. singelton 还将在每次点击单元格时启动计时器并保留对它(即存储 NSIndexPath),以便当您在 detailVCs 和表之间来回跳转时.. 计时器仍按您的要求运行(b/c 它们被单例引用)。 DetailVc 将简单地询问 singelton 它应该显示什么并显示它。

希望这会有所帮助。如果您需要任何进一步的说明,请告诉我。

【讨论】:

  • 嗯...你知道创建单身人士的任何指南吗?
  • 你是说每个任务都应该有一个计时器属性吗?
  • singelton 是一种非常常见的设计模式.. 有一个出色的book 向我介绍了它,称为 head first design patterns.. 不能推荐它。我还建议您查看整本书(当然,在您完成单格顿章节之后:p)b/c 它为您提供了许多关于如何更好地设计软件的想法(即,不仅仅是给您一个链接20 班轮教程)
  • 你上面说过需要多个定时器同时运行,每个定时器对应一个被点击的单元格对吧?在这种情况下,您别无选择,只能为每个点击的单元格存储对 NSTimer 的引用。顺便说一句,singelton 解决方案还解决了您对删除单元格时 NStimer 无效的担忧。
  • 如果它可以解决这个问题,那就完美了。你是在建议我应该继承 UITableViewCell 并添加一个 NSTimer 属性吗?或者我应该给单元格索引路径上的对象 NStimer 属性?
【解决方案2】:

您的代码的问题在于您只创建了一个 DetailViewController 实例,因此每个单元格都推送到同一个单元格。您必须在 didSelectRowAtIndexPath 中有某种方式来查看索引路径并使用它来确定要转到的 DetailViewController 实例。一种方法是创建一个可变字典来保存对 DetailViewController 实例的引用。您可以让键是对应于 indexPath.row 的 NSNumber,值是 DetailViewController 的实例。因此,您的代码可能如下所示:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    DetailViewController *detailVC;
    if (![self.detailControllersDict.allKeys containsObject:@(indexPath.row)]) {
        detailVC = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];
        [self.detailControllersDict setObject:detailVC forKey:@(indexPath.row)];
    }else{
        detailVC = self.detailControllersDict[@(indexPath.row)];
    }
    Tasks *task = [[self fetchedResultsController] objectAtIndexPath:indexPath];
    detailVC.testTask = task;
    [[self navigationController] pushViewController:detailVC animated:YES];

}

detailControllersDict 是指向 NSMutableDictionary 的属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 2018-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多