【问题标题】:Replace "self" under ARC在 ARC 下替换“self”
【发布时间】:2012-11-26 08:03:27
【问题描述】:

通常我从 xib 加载自定义视图的代码如下所示:

@implemenation MyCustomView

- (id)init
{
    [self release];

    if ((self = [[NSBundle loadViewFromXibName:@"MyCustomView" withClass:[MyCustomView class] owner:nil] retain]))
    {
        //some init here
    }

    return self;
}

其中[NSBundle loadViewFromXibName:withClass:owner:] - 返回atoreleased 视图,从xib 加载。

一切正常。 但是当我尝试在 ARC 等效代码下编写时:

@implemenation MyCustomView

- (id)init
{
    if ((self = [NSBundle loadViewFromXibName:@"MyCustomView" withClass:[MyCustomView class] owner:nil]))
    {
        //some init here
    }

    return self;
}

我的应用程序因 EX_BAD_ACCESS 崩溃(释放消息发送到已释放的实例) 在这种情况下会发生什么?我该如何解决这个问题?

已更新 此问题仅在 iOS6 SDK(iOS6 模拟器)上出现。在 iOS5 SDK 和 iOS 5 设备/模拟器上一切正常。

更新这个问题只出现在表格视图单元格中,它在表格视图生命周期中被释放。我实现了静态单元生成器(从 xib 加载的返回单元)并将内部单元初始化移动到 awakeFromNib。现在一切正常。

我不明白为什么会出现这个问题——“self”是__strong,如果我给它分配任何对象,它就不能被自动释放。我记错了吗?

【问题讨论】:

  • loadViewFromXibName == ?
  • 这是一个来自 NSBundle 类别的方法,从 xib 加载并返回 View (autoreleased)。
  • 贴出来的代码没问题。
  • 传统上,你会像这样初始化selfself = [super init],它不会返回一个自动释放的对象。在这里,您将 self 作为一个自动释放的对象返回,这不应该发生在 init 方法中。 [[Class alloc] init] 应该返回一个保留对象,这是 ARC 尊重的(我认为是七个)规则之一。
  • 是的,我想是的。但在 ARC 之下,我可以保留这个对象。 ARC 的解决方法在哪里?

标签: objective-c ios automatic-ref-counting self


【解决方案1】:

我曾经使用这种模式,但在 ARC 之后,我试图通过覆盖 new 来避免它。我不知道为什么这会导致问题,但我猜测两件事之一:

  1. ARC 会在 self = [super init...] 的情况下为您正确处理 [self release],因为 Cocoa 有 init 命名前缀。如果您从 nib(或其他地方)加载,您将不会得到相同的行为
  2. 如果您为self 分配了不是来自[super init...] 的内容,则会丢失您使用[MyCustomView alloc] 分配的内存。

我倾向于认为是后者。如果您是从 nib 加载,我建议您使用工厂方法,例如 new,而不是从 init

编辑:当你说这个问题出现在 iOS 6 上时,我很确定你遇到了我之前遇到的同样问题。当我调试这个时,我什至在dealloc 中放置了一个断点。您会看到每次调用 init 时它都会停在那里一次。

【讨论】:

  • 是的,这是预期的行为。释放空对象并从 xib 加载新对象。
  • “如果你给 self 分配了一些不是来自 [super init...] 的东西,你就会失去你用 [MyCustomView alloc] 分配的内存。”你当然知道。这才是重点。我们正在尝试释放原始对象并保留我们从其他方法获得的对象并返回该对象
【解决方案2】:

改用这个:

NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:@"MyCustomClass" owner:nil options:nil];
self = [nibViews objectAtIndex: 0];

//理想情况下,最好循环遍历该数组,检查哪个视图是您的类的成员并将 self 分配给它。

在你的初始化方法中。

希望这会有所帮助。

干杯!

【讨论】:

  • 这就是 [NSBundle loadViewFromXibName:withClass:owner:] 所做的一切
猜你喜欢
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多