UITableViewCell返回视图后,NSManagedObject数据为<fault>,实体为null

Eri*_*rik 3 core-data uitableview ios swift

我看到使用Swift和Xcode 7.2的Core Data有一些非常奇怪的行为.下面是一个说明问题的动画.

问题

我创建了一个名为"Person"的实体的简单示例,该实体只有一个"name"属性.我获取所有'Person'实体并在表视图中显示它们.如果我强制重新加载单元格,则显示包含名称的textLabel和NSManagedObject objectID而不显示名称.但是,objectID保持不变.这在设备和模拟器中都会发生.

我在"cellForRowAtIndexPath"中将Person实体的值打印到控制台,以便我可以在最初加载单元格时重新加载单元格时显示该值.

人实体价值

正如您所看到的,看起来NSManagedObject仍然存在,尽管它似乎丢失了对其"Person"子类的所有引用.

以下是受影响的ViewController的代码:

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
  let cellIdentifier = "PersonCell"

  @IBOutlet weak var tableView: UITableView!

  var people: NSArray = []

  override func viewDidLoad() {
    super.viewDidLoad()

    people = fetchPeople()
  }

  func fetchPeople() -> NSArray {
    let context = AppDelegate().managedObjectContext
    let fetchRequest = NSFetchRequest(entityName: "Person")
    let sort = NSSortDescriptor(key: "name", ascending: true)
    fetchRequest.sortDescriptors = [sort]

    do {
      let results = try context.executeFetchRequest(fetchRequest)
      return results
    } catch {
      let error = error as NSError
      print("\(error.domain) \(error.code): \(error.localizedDescription)")
      return []
    }
  }

  // MARK: - UITableView methods

  func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
  }

  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return people.count
  }

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)

    let person = people[indexPath.row]
    print("in cellForRowAtIndexPath:")
    print(people[0])

    cell.textLabel?.text = "\(person.name) - \(person.objectID)"
    return cell
  }
}
Run Code Online (Sandbox Code Playgroud)

任何帮助表示赞赏.谢谢.

Mar*_*n R 9

问题出在这里:

let context = AppDelegate().managedObjectContext
Run Code Online (Sandbox Code Playgroud)

您可以创建应用程序委托的新实例,并使用它创建托管对象上下文.一旦程序控制返回fetchPeople(),就不再引用上下文并将其解除分配.结果是访问在此上下文中创建的托管对象的属性返回nil.

你想要的是获得(唯一的)应用程序委托及其托管对象上下文的引用,例如

let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
Run Code Online (Sandbox Code Playgroud)

可替代地,通过上下文视图控制器在didFinishLaunchingWithOptions方法或 prepareForSegue或任何适用于您的应用.