【问题标题】:Re-initialize NSMutableArray as NSMutableArray将 NSMutableArray 重新初始化为 NSMutableArray
【发布时间】:2012-04-27 16:01:27
【问题描述】:

当我在 NSMutableArray 上调用 removeObjectAtIndex 时,我的应用程序抛出异常时遇到问题,说 myLocationsArray 被声明为不可变的。该数组上的所有其他操作都很好,它肯定是正确声明的等等,但是在我的应用程序的某个地方它被设置为不可变的。在调查了一段时间试图找到它被设置为不可变的位置后,我决定搞砸它并重新声明变量:

myLocationsArray = [[NSMutableArray alloc] initWithArray:[defaults
objectForKey:MYLOCATIONSARRAY_KEY]];

就在 removeObjectAtIndex 调用之前。

但是我知道这一定是错误的,我在同一个变量上调用了 alloc/init 两次。然而,这是唯一有效的方法。有没有办法提醒这个变量它是一个 NSMutableArray 而不会像我一样引入内存泄漏?

【问题讨论】:

  • 你需要展示一些处理数组的代码,这可能会导致这种情况,否则任何人都很难提供适当的建议。

标签: objective-c ios


【解决方案1】:

NSUserDefaults 返回数组的不可变副本。无论您将NSArray 还是NSMutableArray 放入其中都没有关系,它总是给您不可变的副本。

所以,这样做是为了获得一个可以使用的可变副本

myLocationsArray = [[NSMutableArray alloc] initWithArray:[[[defaults objectForKey:MYLOCATIONSARRAY_KEY] mutableCopy] autorelease]];

或者只是这个

myLocationsArray = [[defaults objectForKey:MYLOCATIONSARRAY_KEY] mutableCopy];

【讨论】:

  • 我最终意识到问题在于 NSUserDefaults 返回不可变的 NSArrays 但我重新声明它们 NSMutableArrays 来修复它,没有意识到我可以告诉它给我一个可变副本:-D
【解决方案2】:

我建议在程序抛出异常的行(包含removeObjectAtIndex 的行)设置断点,并使用调试器检查数组的真实类型。如果您将鼠标悬停在数组名称上,将显示一个弹出菜单,为您提供有关指向对象所需的所有信息。

我希望你通过这种方式发现对象是一个 NSArray(与 NSMutableArray 相比),然后追溯到你最初初始化它的地方。

【讨论】:

    【解决方案3】:

    您似乎正在使用NSUserDefaults。您从NSUserDefaults 中获得的所有对象始终是不可变的,无论您在其中存储了什么。 NSUserDefaults 不会保留对您设置到其中的特定对象的引用,它会保留 数据。它实际上是在制作副本。当你从NSUserDefaults 中得到一些东西时,它会从它存储的数据中创建一个新的(不可变的)对象并将其提供给你。

    不出所料,您无法通过改变您(认为您自己)存储在其中的内容来更改 NSUserDefaults 中存储的内容。您只能通过重新存储一些内容来替换以前存储的内容来更改存储的内容。

    【讨论】:

    • 是的,原来是 NSUserDefaults。我确保在将数据块从 NSUserDefaults 分配到它之前声明我的 NSMutableArray 并修复它并允许随意突变。谢谢!
    【解决方案4】:

    声明应该无关紧要;您的错误是运行时错误。听起来您的 myLocationsArray 变量已被分配了一个不可变数组 (NSArray),尽管从您的代码片段中无法判断它是在某处重新分配还是始终是不可变的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-29
      • 2012-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多