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

Posted

技术标签:

【中文标题】Swift:从 MainBundle 读取 plist 并直接写入 Documents 失败【英文标题】:Swift: Reading a plist from MainBundle and writing directly to Documents fails 【发布时间】:2016-01-18 08:52:57 【问题描述】:

获取以下文件,命名为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 以来发生了变化,而我能找到的其他问题是由 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 方法会失败?

【问题讨论】:

为什么要检查文件是否存在于捆绑包中?如果你知道它在那里的文件是没有意义的。无法删除或更改位于捆绑包中的文件。 使用返回NSError的写入磁盘API获取更多信息。 你应该创建一个保护语句而不是五个 @LeoDabus 为了示例的目的,我检查了每一步,以明确每一步实际上都通过了。我不会在生产中这样写。 【参考方案1】:

这是错误的:

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

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

let docsURL = NSURL(fileURLWithPath: docsString)

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

let plistString = "\(plistURL)"

改用.path 方法:

let plistPath = plistURL.path!

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

【讨论】:

我的示例中有一个愚蠢的逻辑错误。字符串插值和path 方法有效,但writeToURL() 似乎没有。我已经更新了问题。 @sudomakeinstall:let docsURL = NSURL(string: docsString)也错了,应该是let docsURL = NSURL(fileURLWithPath: docsString) 非常感谢,Martin -- 很抱歉给您添麻烦。

以上是关于Swift:从 MainBundle 读取 plist 并直接写入 Documents 失败的主要内容,如果未能解决你的问题,请参考以下文章

`NSBundle.mainBundle().URLForResource` 总是返回 `nil`

在Swift中逐行读取文本文件?

Swift .writeToFile 不会更新 mainBundle 中的 JSON 文件

MATLAB对ply文件格式的读取和显示

使用 Pymesh 加载和读取 ply 文件

二进制格式 PLY 模型文件的读取与渲染