【问题标题】:TableViewController property changing whilst app is in the background应用程序在后台时 TableViewController 属性发生变化
【发布时间】:2014-04-10 21:33:50
【问题描述】:

我正在慢慢开发我的第一个简单的计时器应用程序,该应用程序开始慢慢变得栩栩如生。目前,当我的应用程序进入后台时,我没有保存数据,目前在编写我的应用程序时,它总是在我的测试过程中保持加载状态,即使它在后台运行了一小段时间。所有这些都是在模拟器上完成的。

我的问题是我有一个带有 NSInteger 索引属性的表视图控制器

   @property NSInteger index;

我用来通过调用 doWork 方法逐步管理 NSArray 上的慢速迭代。

我的 TVC 的初始设置和此属性是在视图准备好从另一个视图转移时执行的。每当我的应用收到本地通知或观察 UIApplicationWillEnterForegroundNotifications 时,都会在此属性和其他属性上完成更多工作。

对此属性的所有访问我都添加了调试日志记录,我只是对我所看到的感到困惑

  • 准备继续
    • @ 19:38:29:058 - 调用方法 doWork 将我的属性从 -1 增加到 0,并设置本地通知。日志显示 self=0x10bb661f0
  • 我按下主页按钮将我的应用置于后台约 10 秒
  • 本地通知触发,我点击横幅使我的应用重新回到焦点
  • 我的 TVC 的 awakeFromNib 函数设置了一个通知观察者 如下

    NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
    [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification 
                                                      object:nil
                                                       queue:mainQueue
                                                  usingBlock:^(NSNotification *note) {
                                                   [self doWork];
                                            }];
    
  • 此通知会触发两次! (出于某种原因?)每次都导致我的 doWork 方法被调用

    • @ 19:38:45:832 - doWork 立即显示我的属性现在恢复为 -1,而不是设置为背景之前的 0,它再次递增到 0。它还显示 self 在 self= 处不同0x10974bbd0,当应用程序处于前台时,它现在保持的值。
    • @ 19:38:45:836 - 在第二次通知调用中再次调用 doWork,我的属性现在正确地从最后一次调用中仍然为 0,它再次增加到 1。
  • 之后,我的应用程序委托也调用了 didReceiveLocalNotification 方法,该方法最终还将通过通知中心观察器设置中的另一个块调用相同的 doWork 方法,与上面详述的设置相同。
    • @ 19:38:45:857 - 调用 doWork 后,该属性再次从设置的 1 变回 0...并再次递增回 1。

我就是不明白发生了什么。我的 TVC 中的大多数属性可能仍然很好,因为我显示 TVC 内容的其余逻辑继续正常工作。为什么我的 NSInteger 会如此混乱?

我认为线程和本地通知处理可能会同时发生一些问题,我希望添加 mainQueue 会对此有所帮助,我之前已将此设置为 nil。遗憾的是它没有任何区别。

我想知道为什么只有很短的时间后,自我就会改变。我天真地假设一切似乎都在回到前台(视图仍然显示,除了这个 NSInteger 属性之外,它的所有数据似乎都完好无损),self ptr 和 object 将是相同的。可以想象它可能以某种方式被操作系统重新定位,但这不应该导致属性发生变化。

我正在使用可可伐木工进行日志记录,并且我已关闭 ASYNC 日志记录,如下所示

    #define LOG_ASYNC_ENABLED NO 

这至少应该意味着日志调用会阻塞,直到它们被记录为止。我可以理解,如果我确实有一些线程问题,那么日志记录顺序可能会有点疑问。但是对于应用程序进入后台后上述属性的初始损坏,从我将 0 写入属性,然后再从其中读取 -1 大约 10 秒。这显然不是线程时间问题。

为什么会两次通知我进入前台?如果我的属性留在我设置它们的地方,那也没关系,但仍然让我觉得有点奇怪。

我在这个块中使用 self 是否有问题,我看到有时您可能希望对这些块使用弱 self 指针,但我也看到了直接使用 self 的示例。

对于理解和希望解决此问题的任何帮助将不胜感激。我有点卡住了,看不出我做错了什么!

干杯

【问题讨论】:

  • 在所有这些过程中,awakeFromNib 被调用了多少次?
  • 听起来好像你有两个不同的对象参与其中,每个对象都有自己的通知。
  • 谢谢你们。你俩都是对的。出于某种原因,我完全忘记了每次新出现的视图时都会调用 awakeFromNib 。我还没有在我的视图控制器中添加任何删除观察者,因为最终我希望能够在我的代码处于活动状态并且这些通知正在触发并在我的模型上工作时能够在几个新视图之间移动。我现在意识到我应该重构并将 doWork 方法移动到我的模型中,然后可以将其传递给任何想要继续使用模型的该方面的视图。
  • 所以因为我已经让通知悬空了,所以我的旧 TVC 一直在闲逛,每个人都会在收到通知时显示自己的警报框...进出这个 TVC 会不断添加新的额外警报随着悬空的 TVC 堆积如山。我在 ViewWillDisappear 中添加了 removeObserver 调用,并且效果很好。我还更改了通知块以使用弱自我指针而不是直接使用自我。谢谢你们的帮助。随意正确回答这个问题,我会感谢你的。否则,我将添加我自己的存根答案,以便任何找到此帖子的人都更清楚。

标签: ios background-process nsnotificationcenter nsinteger foregroundnotification


【解决方案1】:

所以 Woofbeans 和 Phillip Mills 发现我的问题的答案是,每次我进入这个 TVC 时都会调用我的 awakeFromNib,而且我未能在这些通知中删除观察者,导致陈旧的未显示 TVC 无限期地存在.我没有意识到我重现问题的关键部分。

进入 TVC,出来,再进去,然后你会在应用程序中看到重复的警报,这是由于原始 TVC 仍然存在这一事实引起的,被我在我的内部对自我的强烈引用所保留自己的块。

我将把这个 doWork 功能重构到我的模型中,这样它就可以持续存在并得到更好的处理,而与正在显示的任何视图无关。

我还更改了我的块代码以在块内使用弱自指针,以希望阻止该块导致任何对象仅因为被留下的块而持续存在。

大家干杯!

【讨论】:

    猜你喜欢
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-09
    • 2022-07-29
    • 1970-01-01
    相关资源
    最近更新 更多