【问题标题】:storyboardWithName:bundle: is allocating memory for stoyboard object?storyboardWithName:bundle: 为 stoyboard 对象分配内存?
【发布时间】:2016-06-06 12:54:14
【问题描述】:

我们说

NSNumber *number =[[NSNumber alloc] numberWithInetger] 

上面的编辑应该是:

NSNumber *number =[[NSNumber alloc] initWithInteger:0] 

这是为变量分配内存

但这不是:

NSNumber *number = [NSNumber numberWithInteger:1]

现在就我而言,我想调查这条线背后发生了什么:

 _storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
  1. 通过在循环中重复 (storyboardWithName) 方法,我每次分配不同的内存?如果我的故事板很大,这是不好的做法吗?
  2. 如果我在一个方法块中使用此方法 (storyboardWithName),最好只在该方法中定义它吗?完成方法块后会自动释放吗?如果定义为类成员变量呢?
  3. 如果我分配此对象,它何时会被内存管理解除分配 (@autoreleasepool)?*

在我的情况下这基本上意味着什么:

对于这个方法来说:

  • storyboardWithName:bundle:

为指定的故事板创建并返回一个故事板对象 资源文件。

.....

返回值 指定文件的情节提要对象。如果不 故事板资源文件匹配名称存在,抛出异常 带有描述:找不到名为“XXXXXX”的情节提要 捆绑....

讨论 使用此方法检索情节提要对象 包含您要访问的视图控制器图。全部 与故事板关联的资源必须在捆绑包中 由 storyboardBundleOrNil 参数指示。

正在保留对象,但由于我们没有分配/复制,所以不会有 需要释放变量。

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIStoryboard_Class/#//apple_ref/doc/uid/TP40010909-CH1-SW6

更新

这是我从这张幻灯片中了解到的,我有点困惑!

幻灯片链接:http://www.slideshare.net/whalec1/ios-memory-management-basis

【问题讨论】:

  • NSNumber *number 已分配内存。
  • 有几件事:1) 你的第一行代码不应该编译,因为alloc 创建了一个实例,但numberWithInteger 是一个类方法。 2)[NSNumber numberWithInteger:1] 文档说它创建了一个对象,它建议分配内存。 (有可能正在进行共享或缓存,但从调用者的角度来看,它需要被视为正在分配内存。)
  • @PhillipMills 请查看编辑后的代码行
  • 这个更新的代码:NSNumber *number =[[NSNumber alloc] initWithInteger] 仍然是错误的。它应该是NSNumber *number =[[NSNumber alloc] initWithInteger: 1]。您必须添加一个冒号并提供一个整数

标签: ios memory memory-management uistoryboard allocation


【解决方案1】:

你问题的第一部分是错误的。

你说

NSNumber *number = [NSNumber numberWithInteger:1]

不分配内存。当然可以。

该方法是一种“便捷方法”。它是一个内部分配和初始化对象的类方法。

NSNumber 不过是个特例。在内部,系统对常用数值进行了一些特殊处理。例如,如果您创建多个numberWithInteger:1 实例,您将获得指向同一个对象的指针,而不是拥有相同值的多个唯一对象。

对于情节提要,情节提要是一个大而复杂的对象,其中包含其他对象,进行文件管理等。当您使用storyboardWithName 创建情节提要时,系统不会加载情节提要中的所有视图控制器。它创建顶级对象,然后根据需要创建视图控制器。

如果你在循环中重复调用storyboardWithName,那么是的,它每次都会创建一个新对象。不要那样做。您应该在应用程序的生命周期中为每个名称创建一次故事板对象,然后在整个过程中使用该故事板的单个实例。

【讨论】:

  • 所以在你的应用程序的生命周期中,你的意思是我需要创建单例来引用主情节提要吗?顺便说一句,我只有一个主要的故事板。我使用了一些地方`instantiateViewControllerWithIdentifier`,在此之前我使用UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
【解决方案2】:

NSNumber *number =[[NSNumber alloc] numberWithInetger],这是不可能的。这是错误的语法。

NSNumber *number = [NSNumber numberWithInteger:1]绝对分配内存。

_storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 表示_storyboard 是您的Storyboard 的引用,所以它只是指向情节提要或情节提要分配的内存。这不是创建故事板的另一个副本。

【讨论】:

  • 这仍然是错误的。如果你想使用initWithInteger,那么你应该传递整数参数:NSNumber *number = [[NSNumber alloc]initWithInteger:1]; 它会分配内存,NSNumber *number = [NSNumber numberWithInteger:1] 也会分配内存。
  • 感谢您的回答。只是需要多一点解释。如果我说两次:UIStoryboard _storyboard1 = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; UIStoryboard _storyboard2 = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 我是在分配两块内存吗?
  • 实际上,文档建议 storyboardWithName 确实分配一个新的故事板对象。他们说“为指定的故事板资源文件创建并返回一个故事板对象。”不过还不清楚,因为后来文档说“使用此方法检索包含您要访问的视图控制器图形的情节提要对象。”
  • 是的@DuncanC 是对的。这令人困惑,但我认为它不会创建另一个对象,它只是指向情节提要对象。因此,如果您创建多个实例,那么它不会分配情节提要那么多时间,而是指向那么多时间,这意味着创建引用需要那么多时间,因此最好尽可能使用单个实例。
  • 我实际上对此进行了测试,并在每一行上放置了断点。有两个具有不同内存地址的变量。我不确定这是否是变量本身的地址并且它们指向相同的内存地址或者我有两个实例!
【解决方案3】:

在您真正需要它们之前,创建大量故事板对象并不是一个坏习惯。

另外,它可能没有你想象的那么大。当故事板被实例化时,它只是已经被实例化的故事板,在你这样做之前,不会为任何场景分配内存 - (__kindof UIViewController *)instantiateViewControllerWithIdentifier:(NSString *)identifier;

已使用上述方法实例化的 ViewController,具有属性 @property(nullable, nonatomic, readonly, strong) UIStoryboard *storyboard,存储对故事板的强引用。因此,即使本地故事板对象超出范围,该故事板对象也会被控制器强引用,并且在 ViewControllers 被释放之前不会释放。

【讨论】:

  • 感谢您的回答。我想你明白问题的重点。你能解释一下我是否在一个代码块中重复两次A = instantiateViewControllerWithIdentifier:B = instantiateViewControllerWithIdentifier:我是否为每一行分配了不同的内存块。顺便说一下,标识符和情节提要每次都是一样的
  • @Bernard 是的!每次调用 instantiateViewContrller 都会为 viewcontroller 对象分配内存,即使 storyboard 和 id 相同。
  • 你能补充一点关于取消分配的内容吗?将情节提要定义为类成员并在我需要的每个地方都使用它更好,或者我在每个需要它的块中实例化它,然后跳跃内存管理将释放它。哪一个在性能方面更昂贵,而实践这一点的方法更好?
  • @Bernard 我建议你做一个班级成员。这是更好的做法,这样我们可以避免不必要的内存分配
猜你喜欢
  • 1970-01-01
  • 2015-10-15
  • 2014-03-17
  • 1970-01-01
  • 1970-01-01
  • 2013-01-21
  • 1970-01-01
  • 1970-01-01
  • 2021-07-24
相关资源
最近更新 更多