【问题标题】:is it possible to not dealloc a view controller when the back button is pressed in a navigation controller?在导航控制器中按下后退按钮时是否可以不释放视图控制器?
【发布时间】:2013-07-31 11:40:12
【问题描述】:

这是我的问题:我有一个带有一堆单元格的表格视图。 Core Data 使用 NSFetchedResultsController 将 Task 对象加载到单元格中。现在我有了它,所以每个单元格都有一个 DetailViewController,它存储在字典中,如下所示:

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

每个 DetailViewController 都有一个 timer 属性,该属性从 Task 对象获取其时间间隔,该对象与 tableview 中任何给定索引路径处的单元格相关。这是我的详细视图控制器的代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    [NSThread detachNewThreadSelector:@selector(startTimer:) toTarget:self withObject:nil];
}
-(IBAction)startTimer:(id)sender{
//default value of showButtonValue when first loaded is 1
    if (testTask.showButtonValue == 1) {
        [startButton setTitle:@"Start" forState:UIControlStateNormal];
        timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction:) userInfo:nil repeats:YES];
        testTask.showButtonValue = 3;
    } else if (testTask.showButtonValue == 2) {
        [startButton setTitle:@"Resume" forState:UIControlStateNormal];
        [timer invalidate];
        timer = nil;
        testTask.showButtonValue = 3;
    } else if (testTask.showButtonValue == 3){
        [startButton setTitle:@"Pause" forState:UIControlStateNormal];
        timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction:) userInfo:nil repeats:YES];
        testTask.showButtonValue = 2;
    }
}
-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    nameTextField.text = testTask.taskName;
    [timerLabel setFont:[UIFont fontWithName:@"Arial" size:60]];
    NSUInteger seconds = (NSUInteger)round(testTask.timeInterval);
    NSString *string = [NSString stringWithFormat:@"%02u:%02u:%02u",
                        seconds / 3600, (seconds / 60) % 60, seconds % 60];
    timerLabel.text = string;
    [[self navigationItem] setTitle:[testTask taskName]];

    [timerLabel setNeedsDisplay];
    [self.view setNeedsDisplay];
}
-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    testTask.taskName = nameTextField.text;
}
-(void)timerAction:(NSTimer *)t
{
    if(testTask.timeInterval == 0)
    {
        if (self.timer)
        {
            [self timerExpired];
            [self.timer invalidate];
            self.timer = nil;
        }
    }
    else
    {
        testTask.timeInterval--;
    }
    NSUInteger seconds = (NSUInteger)round(testTask.timeInterval);
    NSString *string = [NSString stringWithFormat:@"%02u:%02u:%02u",
                        seconds / 3600, (seconds / 60) % 60, seconds % 60];
    timerLabel.text = string;
    NSLog(@"%f", testTask.timeInterval);
}

无论细节视图控制器当前是否在屏幕上,计时器都应该继续运行。当我第一次点击一个单元格时,转到详细视图控制器并启动计时器,然后返回到表格视图,没有问题并且倒计时继续进行。问题是,如果我重新点击单元格,则会创建另一个计时器,因此时间会以 2 倍的速度递减!不仅如此,显示剩余时间的字符串不会在 ViewWillAppear 时更新,它只会在第一次调用 timerAction 时更新。

有一堆问题,我真的很感激一些帮助!

【问题讨论】:

  • 这是我发布给您的另一个问题的代码。我已经对其进行了测试,当您第二次返回细节控制器时,它不应该(也不在我手中)创建另一个计时器。我在 viewDidLoad 中启动了我的计时器,我不确定你为什么使用 detachNewThreadSelector:。我不认为这是问题所在。尝试在 didSelectRowAtIndexPath 中记录 self.detailViewsDictionary 以确保它不为零。
  • 它说“空”。我猜这不应该发生,哈哈。顺便说一句,谢谢你的帮助!如果可以的话,我会pm你,但没有办法这样做哈哈

标签: iphone ios objective-c dealloc detailview


【解决方案1】:

您在 didSelectRowAtIndexPath 中的代码(我在对您的其他问题 (one timer per detail view controller) 的回答中提供)确实可以防止在您按下后退按钮时释放控制器。它通过在字典中保留对详细视图控制器的引用来做到这一点。我猜它对你不起作用,因为你忘了初始化字典,所以它是 nil。

【讨论】:

  • 老实说,我觉得自己像个白痴(我是初学者,但这并不能原谅我犯这些简单的错误..)。非常感谢你的帮助。我对 NSMutableDictionary 不太熟悉,所以你知道我将如何添加另一个键,以便具有相同索引路径但在不同部分中的 detailviewcontrollers 不会显示相同的详细视图控制器吗?
  • @EvilAegis,而不是使用 NSNumbers(基于 indexPath.row)作为字典的键,您可以使用 indexPath 本身——只有在节和行相同时才会相同.
【解决方案2】:

即使问题已得到解答,我也会发表我的意见。 一方面,我可能是错的,但我不认为防止释放是一个好主意,尤其是对于整个控制器。在 iOS 中,内存必须尽快释放。

但是,通过查看您的代码,我会做一些事情。

  • 将标签创建移至 viewDidLoad,并在 viewWillAppear 中更新其内容
  • 将您的计时器创建和启动放在一个实用程序类中,并使用适当的方法来启动、停止、暂停给定的计时器。该类将确保只有一个(或多个具有分配 ID)的计时器在运行,并且控制器可以要求它。它不是很优雅,但您至少可以为此使用 AppDelegate。

【讨论】:

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