我现在完全被卡住了:
设置
我有一个UISplitViewController。启动应用程序时,一切加载良好,我可以保存、删除、编辑数据,没有问题。然而,当我按下主页按钮(applicationDidEnterBackground
(并返回应用程序时,我会得到一个EXC_BAD_ACCESS (code=1, address=0x60)
这似乎只发生在我的一个特点上。
func configureCell(cell: NoteTableViewCell, atIndexPath indexPath: NSIndexPath) {
let note = fetchController.fetchedResultsController.objectAtIndexPath(indexPath) as! Note
//deal with NSDate's crap
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .MediumStyle
//set date and title Label
cell.dateLabel.text = dateFormatter.stringFromDate(note.date)
cell.titleLabel.text = note.title
}
错误发生在note.date
上,当移除它并放置NSDate()
时,没有错误。请注意,代码中还有note.title
不会崩溃
我对CoreData的背景了解不多,所以我不知道从哪里开始。
潜在重要代码
这是Note NSManagedObject类
class Note: NSManagedObject {
@NSManaged var date: NSDate
@NSManaged var details: String
@NSManaged var title: String
@NSManaged var tag: String
@NSManaged var noteToFolder: NoteData
@NSManaged var noteToData: NSSet
convenience init(date: NSDate, title: String, details: String,tag: String, insertIntoManagedContext context: NSManagedObjectContext){
let entity: AnyObject = NSEntityDescription.entityForName("Note", inManagedObjectContext: context)!
self.init(entity: entity as! NSEntityDescription, insertIntoManagedObjectContext: context)
self.date = date
self.title = title
self.details = details
self.tag = tag
}
func saveNote(title: String, detail: String,
predicate: NSPredicate, fetchRequest: NSFetchRequest,
context: NSManagedObjectContext) {
fetchRequest.predicate = predicate
do {
let fetchResults = try context.executeFetchRequest(fetchRequest) as? [Note]
fetchResults!.first?.title = title
fetchResults!.first?.details = detail
fetchResults!.first?.date = NSDate()
try context.save()
} catch {
print("Couldn't fetch results")
}
这是VC的细节,VC所做的只是加载注释的标题和细节。但即使我不打开这个VC,我也可以重现错误。
func saveNote() {
//configure the request
let predicate = NSPredicate(format: "self == %@", note.objectID)
let fetchRequest = NSFetchRequest(entityName: "Note")
fetchRequest.predicate = predicate
note.saveNote(titleTextField.text!, detail: detailTextView.text,
predicate: predicate, fetchRequest: fetchRequest, context: context!)
}
这是在主VC中(只显示带有注释标题和日期的UITableView
(,当创建新注释时,这在UIAlertViewController
:内调用
let saveAction = UIAlertAction(title: "Save",
style: UIAlertActionStyle.Default,
handler: { (action: UIAlertAction!) -> Void in
//get textfield
let textField = alert.textFields![0]
//Set note title
var noteName: String?
if textField == "" {
noteName = "New Note"
}else {
noteName = textField.text
}
//save the note
_ = Note(date: NSDate(), title: noteName!, details: "",tag: "defaut", insertIntoManagedContext: self.context)
do {
try self.context.save()
} catch {
print("Couldn't save context")
}
})
其他信息
这篇文章最初是用Swift 1.2在Xcode 6.4上写的,从未出现过问题。当我升级时,我遇到了很多现在已经修复的问题,所以这在Xcode 7上从未起过作用。
据我所知,我没有在离开应用程序时调用的任何函数中编写任何内容
我试着启用Exception Breakpoints
,但没有成功。我也没有尝试过实现多线程CoreData。
编辑
当加载Detail VC
,然后离开应用程序并重新打开它时,应用程序加载时不会出现错误。当移回Master VC
时,没有错误,但UITableViewController
是空的。
编辑2
正如@mundi所暗示的,储蓄可能存在问题。我使用的是fetchedResultsController,当检查提取的数据时,我会在控制台中得到这个:
离开应用程序前:
Printing description of note:
<Super_Notes.Note: 0x7fe320c22710> (entity: Note; id: 0xd000000000080000 <x-coredata://48C2DE25-C58B-446F-995F-F97084BCFCCE/Note/p2> ; data: {
date = "2015-10-15 14:50:32 +0000";
details = "This is Zetta ";
noteToData = "<relationship fault: 0x7fe320dbbcb0 'noteToData'>";
noteToFoler = nil;
tag = defaut;
title = Zetta;
})
重新打开应用时
Printing description of note:
<Super_Notes.Note: 0x7fe320c22710> (entity: <null>; id: 0xd000000000080000 <x-coredata://48C2DE25-C58B-446F-995F-F97084BCFCCE/Note/p2> ; data: <fault>)
这是我用来拉纸条的代码:
func configureCell(cell: NoteTableViewCell, atIndexPath indexPath: NSIndexPath) {
let note = fetchController.fetchedResultsController.objectAtIndexPath(indexPath) as! Note
//deal with NSDate's crap
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .MediumStyle
//set date and title Label
cell.dateLabel.text = dateFormatter.stringFromDate(note.date)
cell.titleLabel.text = note.title
}
这就是我配置NSFetchedResultsController
的方式,它在viewDidLoad
:中被调用
func configFetchController() {
//configure fetch controller
fetchController.context = context
let defaultSortDescriptor = NSSortDescriptor(key: "date", ascending: false)
fetchController.sortDescriptors = [defaultSortDescriptor]
fetchController.entity = NSEntityDescription.entityForName("Note", inManagedObjectContext: context)!
fetchController.fetchedResultsController.delegate = self
do {
try fetchController.fetchedResultsController.performFetch()
} catch {
print("An error occured while performing Fetch")
}
}
如果你还需要什么,请告诉我!:-(
谢谢!
离开应用程序时,似乎没有正确保存日期。日期格式化程序将因nil
日期而崩溃。
我认为saveNote
函数什么也不做,因为谓词不检索任何内容。注意谓词
NSPredicate(format: "self == %@", note.objectID)
永远都是假的。这意味着结果的first
将为零,并且没有对象被实际修改或保存。如果你想要一个特定对象的谓词,它应该是
NSPredicate(format: "self = %@", note)
您的saveNote
函数似乎有些做作。只发送要更新的参数并在修改的地方处理保存,会不会简单得多?
func updateNote(newTitle: String, newDetail: String) {
self.title = newTitle
self.detail = newDetail
self.date = NSDate()
}
我怀疑您可能试图在不同的线程上修改对象。这件事更复杂,有很多注意事项,但有一件事与您的原始设计接近,那就是传递上下文和NSManagedObjectID
。
func updateNote(newTitle: String, newDetail: String, context:
NSManagedObjectContext, objectId: NSManagedObjectID) {
let note = context.objectWithID(objectId) as! Note
note.title = newTitle
note.detail = newDetail
note.date = NSDate()
do { try context.save() } catch {}
}
如果你将其用于子上下文,你仍然需要确保在离开应用程序之前保存所有上下文,否则更改不会写入持久存储。