【问题标题】:iOS: Why isn't this View Controller getting pushed onto the Navigation Controller's stack?iOS:为什么这个 View Controller 没有被推送到 Navigation Controller 的堆栈中?
【发布时间】:2011-09-28 11:09:34
【问题描述】:

我有一个模式视图,它是一个导航控制器。当其 UITableView 中的一行被点击时,该行的正确视图控制器应该被初始化并推送到导航控制器的堆栈上(以便屏幕现在显示该视图控制器)。但它不起作用。我一直在尝试调试它一段时间,在调用 pushViewController 时,导航控制器的保留计数似乎为 0。我认为这意味着它已被释放,这是问题的根源。但我不知道为什么。

在以下代码中,AddSportDelegate.m 显示了包含必要导航控制器(_addItemNavController) 的模式视图,该导航控制器使用必要的AddItemTableViewController 进行了初始化。点击由AddItemViewController 管理的表视图的其中一行会调用AddSportDelegateshowAddItemDataView: 方法,这反过来应该将正确的ViewController 推入_addItemNavController 堆栈。但是,正如我在代码中的注释中指出的那样,此时 _addItemNavController 的保留计数为 0。

注意:我意识到这段代码有内存泄漏。为了简洁起见,我删除了一些发布行。我也没有包含应该被推送的视图控制器的代码,因为它目前除了UILabel 识别它是正确的视图控制器之外没有任何东西。

AddItemDelegate.m

@synthesize addItemNavController = _addItemNavController;

- (void)showAddItemViewController:(UIViewController *)viewController
{
    _parentVC = viewController;
    [_parentVC retain];

    tc = [[AddItemTableViewController alloc] init];

    UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonSystemItemDone target:self action:@selector(cancelAdd)];

    tc.navigationItem.leftBarButtonItem = cancelButton;
    tc.title = @"Select a Category";

    _addItemNavController = [[AddItemNavController alloc] initWithRootViewController:tc];

    tc.superViewController = _addItemNavController;

    [_parentVC.navigationController presentModalViewController:_addItemNavController animated:YES];
}

- (void)showAddItemDataView:(SportCategory *)category
{               
    [category retain];

    UIViewController *vc;
    if (category.name == @"Soccer") {
        vc = [[AddSoccerDataViewController alloc] init];
    }else{
        vc = [[AddBaseballDataViewController alloc] init];
    }

    //retain count already 0
    NSLog(@"retain count: %i", [_addItemNavController retainCount]);

    [_addItemNavController.navigationController pushViewController:vc animated:YES];
}

AddItemTableViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];

    _addItemDelegate = [[AddItemDelegate alloc] init];

    SportCategory *soccer = [[SportCategory alloc] initWithCategoryName:@"Soccer"];
    SportCategory *baseball = [[SportCategory alloc] initWithCategoryName:@"Baseball"];

    _categories = [[NSArray alloc] initWithObjects:soccer,baseball,nil];

    [self.tableView reloadData];
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    SportCategory *selectedCategory = [_categories objectAtIndex:[indexPath row]];
    [_addItemDelegate showAddItemDataView:selectedCategory];
}

【问题讨论】:

  • 你在哪里调用 showAddItemViewController?看起来 _addItemNavController 甚至没有分配,如果调用了 showAddItemViewController 然后检查 tc.superViewController 如果你在某个地方调用释放它,如果 tc.superViewController 是变量或分配属性,那么它可以释放 _addItemNavController。

标签: iphone ios ipad memory-management uinavigationcontroller


【解决方案1】:

我要试一试。

if (category.name == @"Soccer")

我来自java背景,但我知道一点客观 - c。我认为您不能将字符串与 == 进行比较,这意味着您的视图控制器从未创建过。也许尝试一个 isEqualToString 方法。

这是我唯一的想法,我可能是错的。但祝你好运。

【讨论】:

  • 你是对的,但正如文斯指出的那样,它仍然应该属于 else 部分,它确实如此(尽管我现在已经进行了更正,谢谢!)。
【解决方案2】:

'==' 运算符不是比较字符串的好方法,但无论如何您的代码都应该属于 else 部分。 关于您的问题, _addItemNavController 必须为零,因为您的 NSLog 打印 0 的保留计数。 方法 -(void)showAddItemViewController:(UIViewController *)viewController 是否在某处调用? 您的视图控制器似乎没有被初始化。

【讨论】:

  • 是的,showAddItemViewController: 确实被调用了。这就是在模式视图中呈现 AddItemNavController 的原因。这确实会发生(通过点击添加按钮)。模态视图确实出现了,并且使用 tc,AddItemTableViewController 正确初始化。
【解决方案3】:

睡了一会儿,我就找到了问题所在。实际上有两个:

1) AddItemDelegate 中的最后一行内容为:

[_addItemNavController.navigationController pushViewController:vc 动画:YES];

但是,_addItemNavController 是导航控制器,所以需要删除 '.navigationController' 部分。

2) 我还需要在 showAddItemViewController 中将 tc.addItemDelegate 分配给 self。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-23
    • 2017-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-08
    • 2012-09-18
    相关资源
    最近更新 更多