Core Data问题:重写init后无法隐藏NSManagedObject便捷初始化方法
问题原因分析与解决方案
为什么添加private重写初始化后init(context:...)可以编译?
这是NSManagedObject特性结合Swift初始化继承规则导致的现象:
- NSManagedObject的核心指定初始化是
init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?),而init(context:)是系统给NSManagedObject加的便捷初始化方法(定义在系统extension中),它内部会调用上述指定初始化。 - 第一个代码示例里,你自定义的
init(object:context:)属于子类的指定初始化(因为它调用了父类的指定初始化)。根据Swift规则,子类一旦实现了自己的指定初始化,就会自动拒绝继承父类的所有指定初始化,同时也无法继承父类的便捷初始化(便捷初始化必须依赖本类或继承来的指定初始化)。所以此时Foo(context:...)编译失败,这正是你想要的“隐藏默认初始化”的效果。 - 当你添加
override private init(entity:insertInto:)后,相当于显式重写了父类的唯一指定初始化,此时子类满足了“继承父类所有指定初始化”的条件。按照Swift规则,子类会自动继承父类的所有便捷初始化,包括init(context:)。哪怕你把重写的指定初始化标记为private,也只是限制外部直接调用它,系统的便捷初始化init(context:)可以在内部调用这个private方法,所以外部就能正常编译Foo(context:...)了。
如何正确隐藏init(context:)便捷初始化?
要彻底禁止外部使用init(context:),只需要保留第一个代码示例的实现即可——不要重写父类的指定初始化init(entity:insertInto:)。此时子类因自定义了指定初始化,不会继承父类的任何便捷初始化,外部只能调用你定义的init(object:context:)。
不用担心Core Data底层无法创建对象:Core Data框架依赖Objective-C运行时,不受Swift访问控制限制,即使子类不重写指定初始化,框架也能正常创建实例。
内容的提问来源于stack exchange,提问作者maroony
相关产品推荐
相关产品推荐

