【问题标题】:NSManagedObject Subclass Name Collides with Swift Foundation TypeNSManagedObject 子类名称与 Swift 基础类型冲突
【发布时间】:2020-11-26 11:12:03
【问题描述】:

我现在正在处理的代码(从另一个团队继承)有一个基于 CoreData 的持久层。

其中一个实体名为“Notification”,它表示客户端应用程序从后端定期轮询的消息(与 APS 无关);对应的 NSManagedObject 子类定义如下:

import Foundation
import CoreData

@objc(Notification) public class Notification: NSManagedObject {

    // etc...

不用说,这个类名会影响the homonymous Foundation type(对应于 Objective-C 端的 NSNotification)。该应用程序不使用 NotificationCenter 机制,因此直到现在都不是问题。

现在我需要为我的一些类引入通知以观察某些应用级事件,并且我不想每次都消除歧义,例如

let notification = Foundation.Notification.Name(...

我知道我不能在不破坏兼容性的情况下更改我的 CoreData 实体的类名,但我认为@objc(Notification) 可以让我更改 Swift 类名;例如:

@objc(Notification) public class AppNotification: NSManagedObject {
//    ^ This stays the same      ^ This changes

...毕竟,CoreData 是一个 Objective-C API。这是有道理的,如果我必须明确指定 Objective-C 桥接类名,也许我可以使用与模型不同的 Swift 类名。

但是不,如果我进行上述更改,我的应用程序会崩溃。

有没有办法解决这个问题,还是我坚持原作者的可怕决定(和缺乏远见)?

【问题讨论】:

  • typealias 用于Foundation.Notification 怎么样?
  • 好主意。现在我必须想出一个体面和有意义的名字
  • 最好避免名称与基于标准 Objective-c 的框架名称发生冲突......它在运行时仍然是 Objective-c,您可能会遇到非常意外和不清楚的运行时麻烦。所以只要让你的名字独一无二,你就能始终确定“谁是谁”。
  • 你有点幸运,因为@objc(Notification) 不会干扰Foundation.Notification - 参考Obj-C 类型是NSNotification。无论如何,您可以更改类名(请参阅我的答案)并且它不应该崩溃。如果它崩溃了,你的代码库中还有一些其他的问题直到现在都被隐藏了(比如有人使用className 来获取实体名称,...)。或者它可能是代码生成问题、旧派生数据……包括堆栈跟踪,这样我们就可以看到发生了什么。

标签: ios objective-c swift core-data


【解决方案1】:

初始状态

假设您在 Swift 中有以下类:

@objc(Notification)
class Notification: NSManagedObject {

}

extension Notification {
    @nonobjc public class func fetchRequest() -> NSFetchRequest<Notification> {
        return NSFetchRequest<Notification>(entityName: "Notification")
    }
}

extension Notification : Identifiable {
}

以及模型中的以下实体:

更改类名

我可以更改班级名称吗?当然。只需更新您的代码:

@objc(MyNotification)
class MyNotification: NSManagedObject {
}

extension MyNotification {
    @nonobjc public class func fetchRequest() -> NSFetchRequest<MyNotification> {
        return NSFetchRequest<MyNotification>(entityName: "Notification")
    }
}

extension MyNotification : Identifiable {
}

还有你的模型:

保持实体名称设置为通知很重要。如果保持实体名称不变,则无需迁移。

其他cmets

  • 如果在这样的更改后崩溃,您应该在问题中包含崩溃和堆栈跟踪。
  • 它可能由于代码中的另一个问题而崩溃。
  • 我看到人们仍然使用className作为实体名称,这是完全错误的,因为NSManagedObject子类名称可以与实体名称不同。也许,这是你的问题?不知道。
  • 这是我们拥有NSEntityDescriptionname 的原因之一。
  • 您可能还注意到我在 Codegen 中使用了Manual/None。那是因为我想在测试类名更改时避免任何代码生成干扰。
  • 您也可以更改实体名称,但您需要迁移。

【讨论】:

  • 这是正确的答案。 Core Data 类名不需要匹配实体名,尽管它们通常会匹配。更改类名对数据模型没有影响,也不需要迁移。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-18
  • 2019-11-23
  • 2015-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-10
相关资源
最近更新 更多