未收到 addSubview 通知

Posted

技术标签:

【中文标题】未收到 addSubview 通知【英文标题】:addSubview notification not received 【发布时间】:2013-01-02 15:24:56 【问题描述】:

我遇到了一个奇怪的问题.. 我想在我当前的视图中添加一个 UIViewcontroller(称为 iView)。 我通过调用来做到这一点

   iView = [[KFKaraokeInfosView alloc] initWithKaraoke:karaoke NibName:@"InfosView" commingFromPlayer:NO];
    iView.songTitle.text = karaoke.title;
    [self.view addSubview:iView.view];

在 iView 的 viewDidLoad 中,我将它作为观察者添加到 NotificationCenter 以获得某个通知,像这样

    - (void)viewDidLoad
    
        [super viewDidLoad];

        self.title = @"About";

        if ([karaoke.styles count] == 0)
        
            [[NSNotificationCenter defaultCenter] postNotificationName:@"GetInfosOfSong" object:self.karaoke];
        
        else
        
            shouldSetup = YES;
        

        [self.navigationController setNavigationBarHidden:NO animated:YES];
        [self.navigationController.navigationBar setBarStyle:UIBarStyleBlack];

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setup) name:GetSongInfos  object:nil];
        [optionsTableView setBackgroundView:nil];

    

问题是当我在初始化时在 iView 上调用 autorelease 方法时,通知永远不会被捕获(因此永远不会调用 setup 方法),但如果我不为 iView 调用 autorelease,它会起作用。

我不明白这种情况下的内存管理,有人可以帮我理解吗?

【问题讨论】:

你能描述一下你想要做什么吗?在视图控制器包含中添加子视图?还是过渡到新观点?您能否分享代表您使用控制器所做的代码?在视图控制器之间转换时,您不应该使用 addSubview 并且在执行视图控制器包含(即,使这个新控制器成为当前控制器所代表的屏幕的一部分)时,您应该执行 addChildViewController 和相关的包含相关调用.最重要的是,答案取决于您要做什么。 您能否将代码添加到您作为观察者添加通知的位置 我正在尝试在视图控制器容器中添加一个子视图,通过像弹出窗口一样显示新视图,我刚刚编辑了我的问题 你能告诉我们你正在做addChildViewControllerdidMoveToParentViewController等的代码吗? 你在 ARC 环境中吗? 【参考方案1】:

容器视图控制器方法可在UIViewController 类参考的Implementing a Container View Controller 中找到, 示例代码可在视图控制器编程指南的Creating Custom Container View Controllers 中找到。

因此,在 ios 5 及更高版本中,您可能应该:

iView = [[[KFKaraokeInfosView alloc] initWithKaraoke:karaoke NibName:@"InfosView" commingFromPlayer:NO] autorelease];
[self addChildViewController:iView];
iView.songTitle.text = karaoke.title;
[self.view addSubview:iView.view];
[iView didMoveToParentViewController:self];

如果这是 iOS 4 或更早版本,它不支持适当的遏制。你可以手动添加它,像你一样添加视图,没有autorelease

iView = [[KFKaraokeInfosView alloc] initWithKaraoke:karaoke NibName:@"InfosView" commingFromPlayer:NO];
iView.songTitle.text = karaoke.title;
[self.view addSubview:iView.view];

您显然会在父视图控制器的某个 ivar 中保留子视图控制器的副本,而不是 autorelease 它,而是在子视图被关闭时明确地 release 子控制器。请注意,由于您在预包含的 iOS4 世界中运行,因此无法保证您的子控制器接收各种事件(众所周知的旋转事件)。但是您应该会收到通知中心事件。


在 iOS 4 中试图伪造包含的丑陋的另一种方法是根本不使用子视图控制器,而只是将子视图添加到父视图。您实际上可以将其添加到父控制器的 NIB,但只需将其隐藏即可。然后,当您想要显示它时,取消隐藏它。但是将所有内容保留在父视图控制器中,它是 NIB。我上面描述的伪装遏制的方法可能有效(我见过人们这样做),但它给了我heebie jeebies。这个比较简单。

【讨论】:

我需要支持IOS 4.3,这个版本支持addChildViewController方法吗? 啊,不。在 iOS 5 之前不支持包含。如果您尝试为子视图设置控制器,在 iOS 4 中会变得一团糟。 @Matthias 啊,不。您的问题是,如果您 autorelease,您的控制器将被丢弃,即使它的视图仍在屏幕上。因此,您确实必须在父视图控制器的某个 ivar 中保留子视图控制器的副本,而不是 autorelease 它,而是在子视图被关闭时明确地 release 控制器。但是由于您在一个预先包含的 iOS4 世界中运行,因此您的子控制器不能保证接收各种事件(众所周知的旋转事件)。 我明白了.. 我只是想每次我向视图添加子视图时,我都必须在之后释放它(比如当我推送一个 uiviewcontroller 时) 不,当你 pushViewController 时,它会为你保留,所以你可以安全地 autorelease 它。当您进行适当的遏制时,addChildViewController 也会为您保留它。但是在这种情况下,你没有什么可以为你保留它,所以你必须自己做,自己手动清理并忍受各种视图控制器事件永远不会到达你的子控制器的事实。但是您应该会收到通知中心事件。

以上是关于未收到 addSubview 通知的主要内容,如果未能解决你的问题,请参考以下文章

应用程序处于后台时未收到后台获取远程通知,并且用户未通过推送通知进入

关闭时未收到 NSNotificationCenter 通知

某些设备在 android 中未收到推送通知

未收到 Phonegap iOS 推送通知

iPhone 未收到推送通知

FCM iOS 项目未收到通知 - FCM 控制台显示成功但设备未收到