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
方法失败,但可以使用 path
或 String
插值方法。为什么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`