不寻常的核心数据行为 - 保存另一个对象的效果?
问题描述:
所以我想学习Swift,并且我确定我做错了什么,但我无法弄清楚可能是什么。不寻常的核心数据行为 - 保存另一个对象的效果?
我正在写一个笔记记录应用程序来帮助自己加快语言的速度。它具有表格视图(由NSArrayController填充)。点击表格视图中的一个注释会显示一个视图控制器,显示该注释的标题和正文。点击添加按钮将创建一个新的笔记管理对象,并将其传递给与用于编辑的视图控制器相同的视图控制器。
编辑笔记时,选择某些文本并按下command-l的用户可以创建一个标题等于所选文本的新笔记。
除了命令-l以外,一切都很好。这种行为是最不寻常的,我敢肯定,这是我造成的。
它是这样的:
- 创建注释并填写标题和正文。假设它被称为“第一”,而身体是“这是第一个,而不是第二个”。
- 选择一些文本('second')并按下command-l。这将保存当前音符,创建一个新的托管对象,填充标题('秒'),并将其显示在视图控制器中。输入正文('This is the second')
- 保存注释。
- 视图控制器现在列出两个注释,因为它应该。点击第一个音符('第一个')现在显示第二个音符的描述。 ( '这是第二个')
下面是一些代码:
从主(表视图)控制器:
override func prepareForSegue(segue: NSStoryboardSegue, sender: AnyObject?) {
if segue.identifier=="CreateNote" {
let nextViewController = segue.destinationController as! DetailViewController
nextViewController.managedContext=self.managedContext
nextViewController.note = NSEntityDescription.insertNewObjectForEntityForName("Note", inManagedObjectContext: managedContext!) as! Note
}
else if segue.identifier=="EditNote" {
let theSelection = tableView.selectedRow
let theNote = noteArrayController?.arrangedObjects[theSelection] as! Note
let nextViewController = segue.destinationController as! DetailViewController
nextViewController.managedContext=self.managedContext
nextViewController.note = theNote
}
}
从细节视图控制器:
import AppKit
class DetailViewController: NSViewController, KeyNotificationProtocol {
@IBOutlet weak var noteTitle: NSTextField!
@IBOutlet var noteBody: TWTextView!
@IBAction func backButton(sender: AnyObject) {
saveNote()
if historyStack.isNotEmpty() {
note=findNoteByName(historyStack.pop())
loadNote()
}
}
@IBAction func dismissButton(sender: AnyObject) {
saveNote()
self.dismissController(self)
}
var managedContext: NSManagedObjectContext?
var note: Note?
var noteNameToLoad: String?
var historyStack = Stack<String>()
override func viewDidLoad() {
super.viewDidLoad()
loadNote()
noteBody.keyDelegate = self
var requestArray: [KeyRequest] = []
requestArray.append(KeyRequest(theFlags: [NSEventModifierFlags.CommandKeyMask],
theKey: "l",
theTag: "link",
theFunc: self.createLink))
noteBody.keysOfInterest=requestArray
}
override func viewWillDisappear() {
saveNote()
}
func keypressWasReceived(keypress: KeyNotificationData) {
keypress.keypressRequest.funcToCall()
}
func createLink() {
print("create link!")
if(noteBody.selectedRange().length>0) {
saveNote()
if let swRange = noteBody.string?.rangeFromNSRange(noteBody.selectedRange()) {
let selectedText = noteBody.string!.substringWithRange(swRange)
let tempNote=findNoteByName(selectedText)
if(tempNote==nil) {
historyStack.push((note?.title)!)
self.note = (NSEntityDescription.insertNewObjectForEntityForName("Note", inManagedObjectContext: managedContext!) as! Note)
self.note!.title=selectedText
self.note!.attributedBody=NSAttributedString(string: "New note")
loadNote()
}
else {
print("note exists")
}
}
}
}
func saveNote() -> BooleanType {
if (managedContext?.hasChanges != nil) {
self.note?.title=noteTitle.stringValue
self.note?.attributedBody=noteBody.textStorage
var saved = false
do {
try managedContext?.save()
saved = true
}
catch let error as NSError {
print("Error saving \(error)", terminator: "")
}
return saved
}
else {
return true
}
}
func loadNote() {
if self.note?.title==nil {
self.note?.title=""
}
noteTitle.stringValue = (self.note?.title)!
if(self.note?.attributedBody?.length>0) {
noteBody.textStorage?.setAttributedString((self.note?.attributedBody)!)
}
else if(self.note?.body?.characters.count>0) {
noteBody.textStorage?.setAttributedString(NSAttributedString(string: (self.note?.body)!))
}
else {
noteBody.textStorage?.setAttributedString(NSAttributedString(string: ""))
}
}
func findNoteByName(noteName: String) -> Note? {
let freq = NSFetchRequest(entityName: "Note")
freq.predicate = NSPredicate(format: "title == %@", noteName)
var result: [Note]=[]
do {
result = try managedContext?.executeFetchRequest(freq) as! [Note]
}
catch let theError as NSError {
print(theError)
result=[]
}
if result.count>0 {
return result[0]
}
else {
return nil
}
}
}
创建第一个注释:
按下Command-L键后,第一个音符被保存,第二注意创建:
保存了第二个音符(点击完成)后,返回到表视图,并点击第一:
所以,试图找出这是怎么回事,我志愿加入了managedObjectContext通知。我这样做是在AppDelegate中,所有的核心数据的东西设置:
func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
NSNotificationCenter.defaultCenter().addObserver(self, selector: "shitHappened:", name: NSManagedObjectContextObjectsDidChangeNotification, object: managedObjectContext)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "shitHappened:", name: NSManagedObjectContextDidSaveNotification, object: managedObjectContext)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "shitHappened:", name: NSManagedObjectContextWillSaveNotification, object: managedObjectContext)
}
func shitHappened(sender: AnyObject) {
print("-- something happened with core data --")
print(sender)
}
监视我的观察者产生的输出,我没有看到的第一个音符正在更新&保存,使得主体设置到第二个!这是来自这个的数据。在这个日志数据的最后,有一个通知说First Note已被修改。哪里?!
-- something happened with core data --
NSConcreteNotification 0x608000045c10 {name = NSObjectsChangedInManagingContextNotification; object = <NSManagedObjectContext: 0x6180001c01e0>; userInfo = {
inserted = "{(\n <testwiki.Note: 0x6100000a8fa0> (entity: Note; id: 0x610000020b40 <x-coredata:///Note/tBCC61422-BDB8-44EB-A1A0-D32126C892354> ; data: {\n attributedBody = nil;\n body = nil;\n title = \"\";\n})\n)}";
managedObjectContext = "<NSManagedObjectContext: 0x6180001c01e0>";
}}
create link!
-- something happened with core data --
NSConcreteNotification 0x61000005af40 {name = NSObjectsChangedInManagingContextNotification; object = <NSManagedObjectContext: 0x6180001c01e0>; userInfo = {
managedObjectContext = "<NSManagedObjectContext: 0x6180001c01e0>";
updated = "{(\n <testwiki.Note: 0x6100000a8fa0> (entity: Note; id: 0x610000020b40 <x-coredata:///Note/tBCC61422-BDB8-44EB-A1A0-D32126C892354> ; data: {\n attributedBody = \"This is the first, not the second.{\\n NSFont = \\\"\\\\\\\"Helvetica 12.00 pt. P [] (0x610000247e90) fobj=0x101b11ca0, spc=3.33\\\\\\\"\\\";\\n NSParagraphStyle = \\\"Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\\\\n 28L,\\\\n 56L,\\\\n 84L,\\\\n 112L,\\\\n 140L,\\\\n 168L,\\\\n 196L,\\\\n 224L,\\\\n 252L,\\\\n 280L,\\\\n 308L,\\\\n 336L\\\\n), DefaultTabInterval 0, Blocks (\\\\n), Lists (\\\\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation YES, HeaderLevel 0\\\";\\n}\";\n body = nil;\n title = \"The First Note\";\n})\n)}";
}}
-- something happened with core data --
NSConcreteNotification 0x61000004dc50 {name = NSManagingContextWillSaveChangesNotification; object = <NSManagedObjectContext: 0x6180001c01e0>}
-- something happened with core data --
NSConcreteNotification 0x61000024c870 {name = NSManagingContextDidSaveChangesNotification; object = <NSManagedObjectContext: 0x6180001c01e0>; userInfo = {
inserted = "{(\n <testwiki.Note: 0x6100000a8fa0> (entity: Note; id: 0x610000228e00 <x-coredata://18C6EA07-F369-4289-B333-53326C2B9DFE/Note/p226> ; data: {\n attributedBody = \"This is the first, not the second.{\\n NSFont = \\\"\\\\\\\"Helvetica 12.00 pt. P [] (0x610000247e90) fobj=0x101b11ca0, spc=3.33\\\\\\\"\\\";\\n NSParagraphStyle = \\\"Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\\\\n 28L,\\\\n 56L,\\\\n 84L,\\\\n 112L,\\\\n 140L,\\\\n 168L,\\\\n 196L,\\\\n 224L,\\\\n 252L,\\\\n 280L,\\\\n 308L,\\\\n 336L\\\\n), DefaultTabInterval 0, Blocks (\\\\n), Lists (\\\\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation YES, HeaderLevel 0\\\";\\n}\";\n body = nil;\n title = \"The First Note\";\n})\n)}";
updated = "{(\n)}";
}}
loadNote
Optional("second")
Optional(New note{
})
-- something happened with core data --
NSConcreteNotification 0x610000053a10 {name = NSObjectsChangedInManagingContextNotification; object = <NSManagedObjectContext: 0x6180001c01e0>; userInfo = {
inserted = "{(\n <testwiki.Note: 0x6100000a9a80> (entity: Note; id: 0x6100002298c0 <x-coredata:///Note/tBCC61422-BDB8-44EB-A1A0-D32126C892355> ; data: {\n attributedBody = \"New note{\\n}\";\n body = nil;\n title = second;\n})\n)}";
managedObjectContext = "<NSManagedObjectContext: 0x6180001c01e0>";
}}
-- something happened with core data --
NSConcreteNotification 0x61800005cbc0 {name = NSObjectsChangedInManagingContextNotification; object = <NSManagedObjectContext: 0x6180001c01e0>; userInfo = {
managedObjectContext = "<NSManagedObjectContext: 0x6180001c01e0>";
updated = "{(\n <testwiki.Note: 0x6100000a9a80> (entity: Note; id: 0x6100002298c0 <x-coredata:///Note/tBCC61422-BDB8-44EB-A1A0-D32126C892355> ; data: {\n attributedBody = \"This is the second.{\\n NSFont = \\\"\\\\\\\"Helvetica 12.00 pt. P [] (0x610000247e90) fobj=0x101b11ca0, spc=3.33\\\\\\\"\\\";\\n NSParagraphStyle = \\\"Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\\\\n 28L,\\\\n 56L,\\\\n 84L,\\\\n 112L,\\\\n 140L,\\\\n 168L,\\\\n 196L,\\\\n 224L,\\\\n 252L,\\\\n 280L,\\\\n 308L,\\\\n 336L\\\\n), DefaultTabInterval 0, Blocks (\\\\n), Lists (\\\\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation YES, HeaderLevel 0\\\";\\n}\";\n body = nil;\n title = second;\n})\n)}";
}}
-- something happened with core data --
NSConcreteNotification 0x618000240d50 {name = NSManagingContextWillSaveChangesNotification; object = <NSManagedObjectContext: 0x6180001c01e0>}
-- something happened with core data --
NSConcreteNotification 0x61800005d970 {name = NSManagingContextDidSaveChangesNotification; object = <NSManagedObjectContext: 0x6180001c01e0>; userInfo = {
inserted = "{(\n <testwiki.Note: 0x6100000a9a80> (entity: Note; id: 0x61800003ac20 <x-coredata://18C6EA07-F369-4289-B333-53326C2B9DFE/Note/p227> ; data: {\n attributedBody = \"This is the second.{\\n NSFont = \\\"\\\\\\\"Helvetica 12.00 pt. P [] (0x610000247e90) fobj=0x101b11ca0, spc=3.33\\\\\\\"\\\";\\n NSParagraphStyle = \\\"Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\\\\n 28L,\\\\n 56L,\\\\n 84L,\\\\n 112L,\\\\n 140L,\\\\n 168L,\\\\n 196L,\\\\n 224L,\\\\n 252L,\\\\n 280L,\\\\n 308L,\\\\n 336L\\\\n), DefaultTabInterval 0, Blocks (\\\\n), Lists (\\\\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation YES, HeaderLevel 0\\\";\\n}\";\n body = nil;\n title = second;\n})\n)}";
updated = "{(\n)}";
}}
-- something happened with core data --
NSConcreteNotification 0x618000242310 {name = NSObjectsChangedInManagingContextNotification; object = <NSManagedObjectContext: 0x6180001c01e0>; userInfo = {
managedObjectContext = "<NSManagedObjectContext: 0x6180001c01e0>";
updated = "{(\n <testwiki.Note: 0x6100000a9a80> (entity: Note; id: 0x61800003ac20 <x-coredata://18C6EA07-F369-4289-B333-53326C2B9DFE/Note/p227> ; data: {\n attributedBody = \"This is the second.{\\n NSFont = \\\"\\\\\\\"Helvetica 12.00 pt. P [] (0x610000247e90) fobj=0x101b11ca0, spc=3.33\\\\\\\"\\\";\\n NSParagraphStyle = \\\"Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\\\\n 28L,\\\\n 56L,\\\\n 84L,\\\\n 112L,\\\\n 140L,\\\\n 168L,\\\\n 196L,\\\\n 224L,\\\\n 252L,\\\\n 280L,\\\\n 308L,\\\\n 336L\\\\n), DefaultTabInterval 0, Blocks (\\\\n), Lists (\\\\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation YES, HeaderLevel 0\\\";\\n}\";\n body = nil;\n title = second;\n})\n)}";
}}
-- something happened with core data --
NSConcreteNotification 0x618000242f40 {name = NSManagingContextWillSaveChangesNotification; object = <NSManagedObjectContext: 0x6180001c01e0>}
-- something happened with core data --
NSConcreteNotification 0x608000046240 {name = NSManagingContextDidSaveChangesNotification; object = <NSManagedObjectContext: 0x6180001c01e0>; userInfo = {
inserted = "{(\n)}";
updated = "{(\n <testwiki.Note: 0x6100000a9a80> (entity: Note; id: 0x61800003ac20 <x-coredata://18C6EA07-F369-4289-B333-53326C2B9DFE/Note/p227> ; data: {\n attributedBody = \"This is the second.{\\n NSFont = \\\"\\\\\\\"Helvetica 12.00 pt. P [] (0x610000247e90) fobj=0x101b11ca0, spc=3.33\\\\\\\"\\\";\\n NSParagraphStyle = \\\"Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\\\\n 28L,\\\\n 56L,\\\\n 84L,\\\\n 112L,\\\\n 140L,\\\\n 168L,\\\\n 196L,\\\\n 224L,\\\\n 252L,\\\\n 280L,\\\\n 308L,\\\\n 336L\\\\n), DefaultTabInterval 0, Blocks (\\\\n), Lists (\\\\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation YES, HeaderLevel 0\\\";\\n}\";\n body = nil;\n title = second;\n})\n)}";
}}
about to segue to editNote
with title
Optional("The First Note")
Optional(This is the second.{
NSFont = "\"Helvetica 12.00 pt. P [] (0x610000247e90) fobj=0x101b11ca0, spc=3.33\"";
NSParagraphStyle = "Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\n 28L,\n 56L,\n 84L,\n 112L,\n 140L,\n 168L,\n 196L,\n 224L,\n 252L,\n 280L,\n 308L,\n 336L\n), DefaultTabInterval 0, Blocks (\n), Lists (\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation YES, HeaderLevel 0";
})
------------------------
loadNote
Optional("The First Note")
Optional(This is the second.{
NSFont = "\"Helvetica 12.00 pt. P [] (0x610000247e90) fobj=0x101b11ca0, spc=3.33\"";
NSParagraphStyle = "Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\n 28L,\n 56L,\n 84L,\n 112L,\n 140L,\n 168L,\n 196L,\n 224L,\n 252L,\n 280L,\n 308L,\n 336L\n), DefaultTabInterval 0, Blocks (\n), Lists (\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation YES, HeaderLevel 0";
})
-- something happened with core data --
NSConcreteNotification 0x618000241aa0 {name = NSObjectsChangedInManagingContextNotification; object = <NSManagedObjectContext: 0x6180001c01e0>; userInfo = {
managedObjectContext = "<NSManagedObjectContext: 0x6180001c01e0>";
updated = "{(\n <testwiki.Note: 0x6100000a8fa0> (entity: Note; id: 0x610000228e00 <x-coredata://18C6EA07-F369-4289-B333-53326C2B9DFE/Note/p226> ; data: {\n attributedBody = \"This is the second.{\\n NSFont = \\\"\\\\\\\"Helvetica 12.00 pt. P [] (0x610000247e90) fobj=0x101b11ca0, spc=3.33\\\\\\\"\\\";\\n NSParagraphStyle = \\\"Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\\\\n 28L,\\\\n 56L,\\\\n 84L,\\\\n 112L,\\\\n 140L,\\\\n 168L,\\\\n 196L,\\\\n 224L,\\\\n 252L,\\\\n 280L,\\\\n 308L,\\\\n 336L\\\\n), DefaultTabInterval 0, Blocks (\\\\n), Lists (\\\\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation YES, HeaderLevel 0\\\";\\n}\";\n body = nil;\n title = \"The First Note\";\n})\n)}";
}}
其他说明:我会留意的命令-1的子类NSTextView与重载的keyDown功能。
编辑:我忽略了指出,如果我创建了一长串笔记,使用command-l从一个到下一个,当我回去看时,那个链中的每个音符都会有相同的音符体在他们身上。
答
所有的权限都指向相同的文本存储。
变化
self.note?.attributedBody=noteBody.textStorage
到
self.note?.attributedBody = NSAttributedString(attributedString: noteBody.textStorage!)
是问题'self.note?.attributedBody = noteBody.textStorage'?所有归属身体指向相同的文本存储。 – Willeke
就是这样!所以我不得不改变saveNote()这一行: self.note .attributedBody = noteBody.textStorage 这些: 让attributedBody = NSAttributedString(attributedString:noteBody.textStorage)? self.note .attributedBody = belongsBody 如果你写了一个答案,我会接受它。 – Chris