iOS:为什么这个视图控制器没有被推送到导航控制器的堆栈上?

发布于 2024-11-18 14:10:23 字数 2710 浏览 1 评论 0原文

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

在以下代码中,AddSportDelegate.m 呈现模态视图,其中包含使用必要的 AddItemTableViewController 初始化的必要导航控制器 (_addItemNavController)。点击由 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];
}

I have a modal view that is a Navigation Controller. When one of the rows in its UITableView gets tapped, the correct View Controller for that row should be initialized and pushed onto the Navigation Controller's stack (so that the screen now shows that View Controller). But it's not working. I've been trying to debug it for a while, and it appears that the Navigation Controller's retain count is 0 at the time pushViewController is called. I assume that means it has been deallocated, and that this is the root of the problem. But I can't figure out why.

In the following code, AddSportDelegate.m presents the modal view that contains the necessary Navigation Controller (_addItemNavController) initialized with the necessary AddItemTableViewController. Tapping on one of the rows of the Table View managed by AddItemViewController calls the showAddItemDataView: method of AddSportDelegate, which in turn should push the correct ViewController onto the _addItemNavController stack. But, as I note in a comment in the code, the retain count of _addItemNavController at that moment is 0.

Note: I realize this code has memory leaks. I deleted some release lines for the sake of brevity. I also haven't included the code for the view controller that is supposed to be getting pushed, since it doesn't have anything at the moment beyond a UILabel identifying that it is the right View Controller.

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];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浅暮の光 2024-11-25 14:10:23

我打算尝试一下。

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

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

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

I am going to take a shot at this.

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

I come from a java background, but I know a little objective - c. I thought you can't compare strings with == which would mean your view controller was never created. Maybe try a isEqualToString method.

That is my only thought, I could be wrong. But Best of Luck.

爱,才寂寞 2024-11-25 14:10:23

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

The '==' operator isn't the good way to compare strings, but anyway your code should fall into the else part.
About your question, _addItemNavController must be nil because your NSLog prints 0 for its retain count.
Is the method -(void)showAddItemViewController:(UIViewController *)viewController called somewhere ?
Your view controller doesn't seem to be initialized.

旧故 2024-11-25 14:10:23

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

1)AddItemDelegate 中的最后一行是:

[_addItemNavController.navigationController PushViewController:vcanimated:YES];

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

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

A bit of sleep helped me find the problem. There were actually two:

1) The final line in AddItemDelegate read:

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

However, _addItemNavController IS the navigation controller, so the '.navigationController' part needed to be deleted.

2) I also needed to assign tc.addItemDelegate to self in showAddItemViewController.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文