Xcode9.3升级后@property(retain)属性合成报错求助
问题原因及解决方案
这个问题我之前帮同事排查过,其实是Xcode 9.3升级了底层编译器(LLVM 8.0)后,对@property自动合成的规则做了更严格的校验导致的,具体原因和解决思路如下:
核心触发原因
Xcode 9.2及更早版本的编译器对重复同名@property声明的处理比较宽松——哪怕同一个类、分类或者父子类之间存在多个同名的@property,只要没有明显的语法错误,编译器会默默选择其中一个进行合成,不会报错。
但Xcode 9.3对应的LLVM 8.0开始,把这种「存在歧义的@property声明」直接标记为错误,因为这种情况很容易导致内存语义不一致(比如一个声明是retain,另一个是assign),进而引发野指针、内存泄漏等潜在问题。你的报错信息Property with attribute 'retain (or strong)' was selected for synthesis就是编译器在告诉你:它无法确定该用哪个同名@property的规则来合成setter/getter。
结合你的场景分析
你提到项目里有多个同名变量myVariable,这几乎肯定是触发报错的关键,常见的情况包括:
- 同一个类的头文件/实现文件里重复声明了
@property (nonatomic, retain) NSNumber* myVariable; - 某个分类(Category)中也声明了同名的
@property,且内存语义和主类不一致 - 父类已经定义了
myVariable这个@property,子类又重新声明了一遍,且语义冲突
快速解决步骤
- 全局搜索定位重复声明:在Xcode里用「Find in Project」搜索
myVariable,找出所有包含这个属性的@property声明 - 统一内存语义:把所有同名@property的声明改成一致的语义,比如统一用
strong(ARC下retain和strong等价,用strong更符合现代Objective-C规范),示例:@property (nonatomic, strong) NSNumber* myVariable; - 处理分类中的同名属性:如果是分类里的声明,要么直接删除分类中的这个@property(因为分类无法自动合成实例变量,声明了也没用),要么手动实现它的setter/getter方法
- 父子类场景优化:如果是子类重复声明了父类的@property,直接删除子类里的声明即可——子类可以直接继承使用父类的属性;如果确实需要重写,记得加上
@dynamic告诉编译器不要自动合成,然后手动实现setter/getter
内容的提问来源于stack exchange,提问作者Sashah
相关产品推荐
相关产品推荐

