Swift:从 MainBundle 读取 plist 并直接写入 Documents 失败

Swift: Reading a plist from MainBundle and writing directly to Documents fails

获取以下文件,命名为 Permissions.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
    <key>SomeKey</key>
    <false/>
    </dict>
</plist>

我想从我的 MainBundle 中读取它,修改它,然后将它写到我的 .Documents 中。但是,即使我保留它 未修改 ,写入也会失败。 Swift 语法似乎自 this question, and the other questions I could find were caused by incorrect key types 以来发生了变化,考虑到我在写出之前没有修改,这会很奇怪。这是重现错误的完整代码:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Read in the plist from the main bundle.
        guard let path = NSBundle.mainBundle().pathForResource("Permissions", ofType: "plist") else {
            NSLog("Path could not be created.")
            return
        }

        guard NSFileManager.defaultManager().fileExistsAtPath(path) else {
            NSLog("File does not exist.")
            return
        }

        guard let resultDictionary = NSMutableDictionary(contentsOfFile: path) else {
            NSLog("Contents could not be read.")
            return
        }

        print(resultDictionary) // { Facebook = 0; }

        // Write it to the documents directory
        let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray

        guard let docsString = paths[0] as? String else {
            NSLog("Couldn't find documents directory; permissions could not be updated.")
            return
        }

        guard let docsURL = NSURL(string: docsString) else {
            NSLog("Couldn't convert the path to a URL; permissions could not be updated.")
            return
        }

        let plistURL = docsURL.URLByAppendingPathComponent("Permissions.plist")
        let plistPath = plistURL.path!
        let plistString = "\(plistURL)"

        if !resultDictionary.writeToURL(plistURL, atomically: false) {
            NSLog("Writing file to disk via url was unsucessful.") // Failure
        }

        if !resultDictionary.writeToFile(plistPath, atomically: false) {
            NSLog("Writing file to disk via path was unsucessful.")
        }

        if !resultDictionary.writeToFile(plistString, atomically: false) {
            NSLog("Writing file to disk via path was unsucessful.")
        }

        print("URL: ",NSMutableDictionary(contentsOfURL: plistURL)) // nil
        print("Path: ",NSMutableDictionary(contentsOfFile: plistPath)) // Prints
        print("String: ",NSMutableDictionary(contentsOfFile: plistString)) // Prints

    }

}

编辑

我在原始示例中犯了一个愚蠢的逻辑错误(在最后一行中缺少 !),这导致它看起来好像失败了,但实际上并没有。但是,该示例现在使用 URL 方法失败,但可以使用 pathString 插值方法。为什么 URL 方法失败?

这是错误的:

guard let docsURL = NSURL(string: docsString) else { ... }

要从文件路径创建 NSURL,请使用

let docsURL = NSURL(fileURLWithPath: docsString)

反之,不能使用字符串插值来创建文件路径 来自 NSURL

let plistString = "\(plistURL)"

改用.path方法:

let plistPath = plistURL.path!

或者更好的是,使用 writeToURL() 方法编写字典, 那么您不必将 URL 转换为路径。