Objective c 目标C初始怪癖

Objective c 目标C初始怪癖,objective-c,automatic-ref-counting,initializer,autorelease,Objective C,Automatic Ref Counting,Initializer,Autorelease,在类接口中,我定义了一些ivar @property (strong,nonatomic) id < Protocol > initEst; // Initial estimate @property(强,非原子)idinitEst;//初步估计 这编译没有问题,但当我运行程序时,它会崩溃,原因是调试器指示的EXC\u BAD\u ACCESS和[Object.cxx\u destruct] 发生了什么事?我已经对这个问题进行了更多的测试,似乎有三个条件使得这个特殊的怪癖出现

在类接口中,我定义了一些ivar

@property (strong,nonatomic) id < Protocol > initEst;   // Initial estimate
@property(强,非原子)idinitEst;//初步估计
这编译没有问题,但当我运行程序时,它会崩溃,原因是调试器指示的EXC\u BAD\u ACCESS[Object.cxx\u destruct]


发生了什么事?

我已经对这个问题进行了更多的测试,似乎有三个条件使得这个特殊的怪癖出现

在我的特殊情况下,ivar的
协议也与包含类的协议相同。这似乎是这个问题浮出水面的一个额外要求(参考我之前的答案,这里没有提到这一点)

因此,我想详细说明我先前的回答。如果

  • initXXX
    是一个ivar
  • 属于
    id
    类型
  • 它实现了与包含类相同的
    协议
  • 然后Objective-C+ARC编译器将愉快地编译代码,但无法执行它

    下面是我用来测试的代码示例

    @interface Dog : NSObject < Animal >
    
    @property (nonatomic,strong) id < Animal > initState;
    
    @end
    
    @接口狗:NSObject
    @属性(非原子,强)idinitState;
    @结束
    
    这样做只会导致问题,因为名称以init开头。更改名称,所有问题都会消失

    作为参考,此操作生成的运行时错误为

    Dog对象在已解除分配时已过度释放

    这段代码相当抽象,但在需要指定某些初始条件的地方,以及在自然命名某些ivar
    initXxx
    的地方,这可能会对您造成伤害,但请注意,如果您使用Objective-C,您既没有这种奢侈,编译器也不会警告您它是错误的


    最初的错误似乎与内存分配有关,并使我怀疑我使用自动释放池的方式,但现在我相当确信这与问题无关。

    我已经对这一问题进行了更多的测试,似乎有三个条件让这个特殊的怪癖出现

    在我的特殊情况下,ivar的
    协议也与包含类的协议相同。这似乎是这个问题浮出水面的一个额外要求(参考我之前的答案,这里没有提到这一点)

    因此,我想详细说明我先前的回答。如果

  • initXXX
    是一个ivar
  • 属于
    id
    类型
  • 它实现了与包含类相同的
    协议
  • 然后Objective-C+ARC编译器将愉快地编译代码,但无法执行它

    下面是我用来测试的代码示例

    @interface Dog : NSObject < Animal >
    
    @property (nonatomic,strong) id < Animal > initState;
    
    @end
    
    @接口狗:NSObject
    @属性(非原子,强)idinitState;
    @结束
    
    这样做只会导致问题,因为名称以init开头。更改名称,所有问题都会消失

    作为参考,此操作生成的运行时错误为

    Dog对象在已解除分配时已过度释放

    这段代码相当抽象,但在需要指定某些初始条件的地方,以及在自然命名某些ivar
    initXxx
    的地方,这可能会对您造成伤害,但请注意,如果您使用Objective-C,您既没有这种奢侈,编译器也不会警告您它是错误的


    最初的错误似乎与内存分配有关,使我怀疑我使用自动释放池的方式,但现在我确信这与问题无关。

    这都是关于ARC自动内存管理的规则。初始值设定项具有处理返回值的特殊规则:保留和返回。看

    一般来说,Objective-C,特别是ARC,对方法名称的含义有一些非常严格的规则
    initXXX
    表示“这是一个初始值设定项”。如果这不是初始值设定项,请不要使用
    init
    前缀


    您可以完全关闭ARC并自己管理内存,但遵守约定更容易,而且它更适合与其他语言(如Swift)交互。

    这都是关于ARC自动内存管理的规则。初始值设定项具有处理返回值的特殊规则:保留和返回。看

    一般来说,Objective-C,特别是ARC,对方法名称的含义有一些非常严格的规则
    initXXX
    表示“这是一个初始值设定项”。如果这不是初始值设定项,请不要使用
    init
    前缀


    您可以完全关闭ARC并自己管理内存,但遵守约定更容易,而且它更适合与其他语言(如Swift)交互。

    我接受
    init
    的问题,但即使链接也只与方法相关。我根本没有使用一种方法,很惊讶它被如此对待。如果我没有使用ARC,我可以保留并自动恢复它。我想特别了解在自动释放内部分配和外部使用时,ARC和自动释放池是如何协同工作的。@skaak
    self.initEst=…
    [self-setInitEst:…]相同
    。如果
    initEst
    指向普通对象,编译器将抱怨
    init
    部分,但如果它是
    id
    指针,则不会抱怨,因此只能执行
    self.initEst=
    [self-setInitEst:…]
    如果它是一个
    id
    指针。我接受
    init
    的问题,但即使链接也只将
    init
    与方法联系起来。我根本没有使用一种方法,很惊讶它被如此对待。如果我没有使用ARC,我可以保留并自动恢复它。我想特别了解在自动释放内部分配和外部使用时,ARC和自动释放池是如何协同工作的。@skaak