应用程序未从 .plist 文件中删除一行

App not deleting a row from .plist file

在我正在从事的一个项目中,我有一个类似笔记的功能,它充当 Exercise/Training 日志。本培训日志由 5 个文件组成:Note.swift、NotesTableViewController.swift、NoteDetailViewController.swift、NoteDetailTableViewCell.swift 和 NoteStore.swift。这个 table 的 class 是 NotesTableViewController,它是一个带有 UITableViewDelegate 和 UITableViewDataSource 的 UIViewController。此笔记功能运行良好,填充 table 视图,但无法从 .plist 文件中删除笔记,并在重新打开应用程序时继续检索它。我不知道这是否真的 save/load 失败,或者其他地方出了问题。我将不胜感激任何帮助。文件如下:

Note.swift

import Foundation

class Note : NSObject, NSCoding {
var title = ""
var text = ""
var date = NSDate() // Defaults to current date / time

// Computed property to return date as a string
var shortDate : NSString {
    let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "MM/dd/yy"
        return dateFormatter.stringFromDate(self.date)
}

override init() {
    super.init()
}

// 1: Encode ourselves...
func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(title, forKey: "title")
    aCoder.encodeObject(text, forKey: "text")
    aCoder.encodeObject(date, forKey: "date")
}

// 2: Decode ourselves on init
required init(coder aDecoder: NSCoder) {
    self.title = aDecoder.decodeObjectForKey("title") as! String
    self.text  = aDecoder.decodeObjectForKey("text") as! String
    self.date   = aDecoder.decodeObjectForKey("date") as! NSDate
}

}

NotesTableViewController.swift

import UIKit

class NotesTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

@IBOutlet weak var tableView: UITableView!

@IBOutlet weak var OpenButton: UIBarButtonItem!

override func viewDidLoad() {
    super.viewDidLoad()

    // Leverage the built in TableViewController Edit button
    self.navigationItem.leftBarButtonItem = self.editButtonItem()

    OpenButton.target = self.revealViewController()
    OpenButton.action = Selector("revealToggle:")

    self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())

    self.tableView.reloadData()

}

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    // ensure we are not in edit mode
    editing = false
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // Here we pass the note they tapped on between the view controllers
    if segue.identifier == "NoteDetailPush" {
        // Get the controller we are going to
        var noteDetail = segue.destinationViewController as! NoteDetailViewController
        // Lookup the data we want to pass
        var theCell = sender as! NoteDetailTableViewCell
        // Pass the data forward
        noteDetail.theNote = theCell.theNote
    }
}


@IBAction func saveFromNoteDetail(segue:UIStoryboardSegue) {
    // We come here from an exit segue when they hit save on the detail screen

    // Get the controller we are coming from
    var noteDetail = segue.sourceViewController as! NoteDetailViewController

    // If there is a row selected....
    if let indexPath = tableView.indexPathForSelectedRow() {
        // Update note in our store
        NoteStore.sharedNoteStore.updateNote(theNote: noteDetail.theNote)

        // The user was in edit mode
        tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
    } else {
        // Otherwise, add a new record
        NoteStore.sharedNoteStore.createNote(theNote: noteDetail.theNote)

        // Get an index to insert the row at
        var indexPath = NSIndexPath(forRow: NoteStore.sharedNoteStore.count()-1, inSection: 0)

        // Update tableview
        tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
    }
}

// MARK: - Table view data source

  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // Just return the note count
    return NoteStore.sharedNoteStore.count()
}


 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    // Fetch a reusable cell
    let cell = tableView.dequeueReusableCellWithIdentifier("NoteDetailTableViewCell", forIndexPath: indexPath) as! NoteDetailTableViewCell

    // Fetch the note
    var rowNumber = indexPath.row
    var theNote = NoteStore.sharedNoteStore.getNote(rowNumber)

    // Configure the cell
    cell.setupCell(theNote)

    return cell
}


// Override to support editing the table view.
 func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {

    if editingStyle == .Delete {
        // Delete the row from the data source
        NoteStore.sharedNoteStore.deleteNote(indexPath.row)
        // Delete the note from the tableview
        tableView.deleteRowsAtIndexPaths([indexPath],        withRowAnimation: .Fade)
    }
}


}

NoteDetailViewController

import UIKit

class NoteDetailViewController: UIViewController {

var theNote = Note()

@IBOutlet weak var noteTitleLabel: UITextField!

@IBOutlet weak var noteTextView: UITextView!

override func viewDidLoad() {
    super.viewDidLoad()

    // The view starts here. By now we either have a note to edit
    // or we have a blank note in theNote property we can use

    // Update the screen with the contents of theNote
    self.noteTitleLabel.text = theNote.title
    self.noteTextView.text = theNote.text

    // Set the Cursor in the note text area
    self.noteTextView.becomeFirstResponder()
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // Whenever we leave the screen, update our note model
    theNote.title = self.noteTitleLabel.text
    theNote.text = self.noteTextView.text
}

@IBAction func CancelNote(sender: AnyObject) {

    self.dismissViewControllerAnimated(true, completion: nil)

}
}

NoteDetailTableViewCell

import UIKit

class NoteDetailTableViewCell : UITableViewCell {

// The note currently being shown
weak var theNote : Note!

// Interface builder outlets
@IBOutlet weak var noteTitleLabel : UILabel!
@IBOutlet weak var noteDateLabel : UILabel!
@IBOutlet weak var noteTextLabel : UILabel!

// Insert note contents into the cell
func setupCell(theNote:Note) {
    // Save a weak reference to the note
    self.theNote = theNote

    // Update the cell
    noteTitleLabel.text = theNote.title
    noteTextLabel.text = theNote.text
    noteDateLabel.text = theNote.shortDate as String
}

}

最后,NoteStore

import Foundation

class NoteStore {
// Mark: Singleton Pattern (hacked since we don't have class var's yet)
class var sharedNoteStore : NoteStore {
struct Static {
    static let instance : NoteStore = NoteStore()
    }
    return Static.instance
}

// Private init to force usage of singleton
private init() {
    load()
}

// Array to hold our notes
private var notes : [Note]!

// CRUD - Create, Read, Update, Delete

// Create

func createNote(theNote:Note = Note()) -> Note {
    notes.append(theNote)
    return theNote
}

// Read

func getNote(index:Int) -> Note {
    return notes[index]
}

// Update
func updateNote(#theNote:Note) {
    // Notes passed by reference, no update code needed
}

// Delete
func deleteNote(index:Int) {
    notes.removeAtIndex(index)
}

func deleteNote(withNote:Note) {

    for (i, note) in enumerate(notes) {
        if note === withNote {
            notes.removeAtIndex(i)
            return
        }
    }

}

// Count
func count() -> Int {
    return notes.count
}


// Mark: Persistence

// 1: Find the file & directory we want to save to...
func archiveFilePath() -> String {
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
    let documentsDirectory = paths.first as! NSString
    let path = documentsDirectory.stringByAppendingPathComponent("NoteStore.plist")

    return path
}

// 2: Do the save to disk.....
func save() {
    NSKeyedArchiver.archiveRootObject(notes, toFile: archiveFilePath())
}


// 3: Do the reload from disk....
func load() {
    let filePath = archiveFilePath()
    let fileManager = NSFileManager.defaultManager()

    if fileManager.fileExistsAtPath(filePath) {
        notes = NSKeyedUnarchiver.unarchiveObjectWithFile(filePath) as! [Note]
    } else {
        notes = [Note]()
    }
}

}

看起来你在更改创建、删除或更新笔记后没有调用保存方法

您可以添加例如:

func deleteNote(index:Int) {
notes.removeAtIndex(index)
save()   
}

如果您不想在每次更改后都编写新的 plist,或者调用 vievWillDisappear 上的保存方法