3

我为两个核心数据实体生成了类。第一个称为地址,是一个抽象实体。第二个称为 Person,它继承自 Address。出于此测试的目的,我添加了一些示例托管属性。而且我已经向 Person 类添加了一个非托管 String 属性。访问 Person 类的字符串属性会崩溃。为什么会崩溃?

Address 和 Person 类由 Xcode 自动生成,除了额外的参数:let foo = "Foo"

如果我修改代码以使 Person 直接从 NSManagedObject 继承而不是 Address,那么代码可以正常工作并且不会崩溃。

自动生成的地址类:

@objc(Address)
public class Address: NSManagedObject {
}

extension Address {
    @nonobjc public class func fetchRequest() -> NSFetchRequest<Address> {
        return NSFetchRequest<Address>(entityName: "Address")
    }
    @NSManaged public var street: String?
    @NSManaged public var city: String?
}

自动生成的人员类,“foo”参数除外:

@objc(Person)
public class Person: Address {
    public let foo = "Foo"  //added this parameter
}

extension Person {
    @nonobjc public class func fetchRequest() -> NSFetchRequest<Person> {
        return NSFetchRequest<Person>(entityName: "Person")
    }
    @NSManaged public var name: String?
}

问题代码

let person = Person(context: context)
print(person.foo) //doesn't crash, but prints empty line instead of value
print("VALUE:\(person.foo):") //crashes with Thread 1: EXC_BAD_ACCESS (code=1, address=0x18)

更新:如果 foo 被定义为

public let foo: String? = "Foo"

那么打印语句不会崩溃,而是将值解释为“nil”并打印出来。

所以我的问题变成了:为什么这个被分配为常数的值在幕后被重置为零?

4

1 回答 1

0

我有两个挥手解释为什么你得到零:

将这两者放在一起,你会得到一个不起作用的边缘案例。

话虽这么说,我有点惊讶您的foo设置不起作用,因为foo它不是托管属性(也就是说,它不在数据模型中)。如果我在常规的非托管对象中 创建这样一个常量存储属性……</p>

public class Animal {
    public let foo: String! = "Foo"
}

它稍后会按预期回读。

因此,如果您可以接受这种极端情况在 Core Data中不起作用,您可以继续采用几种更正常的方法。

一种方法是在插入之后声明foo为 avar并为其分配一个值awakeFromInsert(),正如我之前提到的那样。在 Core Data 中,awakeFromInsert()是您的一位朋友……</p>

@objc(Person)
public class Person: Address {
    public var foo: String!
    override public func awakeFromInsert() {
        foo = "Foo"
    }
}

另一种工作方式是作为计算属性......</p>

@objc(Person)
public class Person: Address {
    public var foo : String { return "Foo" }
}

最后,最合乎逻辑的方法是,因为 foo 对于所有实例都是常量,所以将其设为类型属性……</p>

@objc(Person)
public class Person: Address {
    static var foo: String = "Foo"
}

但当然,如果您这样做,您必须将其引用为Person.foo而不是person.foo.

于 2019-03-30T22:35:58.980 回答