Objective c 目标C初始怪癖
在类接口中,我定义了一些ivarObjective 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] 发生了什么事?我已经对这个问题进行了更多的测试,似乎有三个条件使得这个特殊的怪癖出现
@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对象在已解除分配时已过度释放
这段代码相当抽象,但在需要指定某些初始条件的地方,以及在自然命名某些ivarinitXxx
的地方,这可能会对您造成伤害,但请注意,如果您使用Objective-C,您既没有这种奢侈,编译器也不会警告您它是错误的
最初的错误似乎与内存分配有关,并使我怀疑我使用自动释放池的方式,但现在我相当确信这与问题无关。我已经对这一问题进行了更多的测试,似乎有三个条件让这个特殊的怪癖出现
在我的特殊情况下,ivar的协议也与包含类的协议相同。这似乎是这个问题浮出水面的一个额外要求(参考我之前的答案,这里没有提到这一点)
因此,我想详细说明我先前的回答。如果
initXXX
是一个ivar
属于id
类型
它实现了与包含类相同的协议
然后Objective-C+ARC编译器将愉快地编译代码,但无法执行它
下面是我用来测试的代码示例
@interface Dog : NSObject < Animal >
@property (nonatomic,strong) id < Animal > initState;
@end
@接口狗:NSObject
@属性(非原子,强)idinitState;
@结束
这样做只会导致问题,因为名称以init开头。更改名称,所有问题都会消失
作为参考,此操作生成的运行时错误为
Dog对象在已解除分配时已过度释放
这段代码相当抽象,但在需要指定某些初始条件的地方,以及在自然命名某些ivarinitXxx
的地方,这可能会对您造成伤害,但请注意,如果您使用Objective-C,您既没有这种奢侈,编译器也不会警告您它是错误的
最初的错误似乎与内存分配有关,使我怀疑我使用自动释放池的方式,但现在我确信这与问题无关。这都是关于ARC自动内存管理的规则。初始值设定项具有处理返回值的特殊规则:保留和返回。看
一般来说,Objective-C,特别是ARC,对方法名称的含义有一些非常严格的规则initXXX
表示“这是一个初始值设定项”。如果这不是初始值设定项,请不要使用init
前缀
您可以完全关闭ARC并自己管理内存,但遵守约定更容易,而且它更适合与其他语言(如Swift)交互。这都是关于ARC自动内存管理的规则。初始值设定项具有处理返回值的特殊规则:保留和返回。看
一般来说,Objective-C,特别是ARC,对方法名称的含义有一些非常严格的规则initXXX
表示“这是一个初始值设定项”。如果这不是初始值设定项,请不要使用init
前缀
您可以完全关闭ARC并自己管理内存,但遵守约定更容易,而且它更适合与其他语言(如Swift)交互。我接受init
的问题,但即使链接也只与方法相关。我根本没有使用一种方法,很惊讶它被如此对待。如果我没有使用ARC,我可以保留并自动恢复它。我想特别了解在自动释放内部分配和外部使用时,ARC和自动释放池是如何协同工作的。@skaakself.initEst=…
与[self-setInitEst:…]相同
。如果initEst
指向普通对象,编译器将抱怨init
部分,但如果它是id
指针,则不会抱怨,因此只能执行self.initEst=
或[self-setInitEst:…]
如果它是一个id
指针。我接受init
的问题,但即使链接也只将init
与方法联系起来。我根本没有使用一种方法,很惊讶它被如此对待。如果我没有使用ARC,我可以保留并自动恢复它。我想特别了解在自动释放内部分配和外部使用时,ARC和自动释放池是如何协同工作的。@skaak