我在玩苹果的新Swift编程语言,遇到了一些问题…
目前我试图读取一个plist文件,在Objective-C中,我会做以下工作来获取内容作为NSDictionary:
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Config" ofType:@"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:filePath];
我如何得到一个plist作为一个字典在Swift?
我假设我可以得到路径到plist:
let path = NSBundle.mainBundle().pathForResource("Config", ofType: "plist")
当这工作(如果它是正确的?):我如何获得内容作为一个字典?
还有一个更普遍的问题:
是否可以使用默认的NS*类?我想是的……还是我遗漏了什么?据我所知,默认框架NS*类仍然有效,可以使用吗?
我使用swift字典,但在我的文件管理器类中转换它们和nsdictionary,如下所示:
func writePlist(fileName:String, myDict:Dictionary<String, AnyObject>){
let docsDir:String = dirPaths[0] as String
let docPath = docsDir + "/" + fileName
let thisDict = myDict as NSDictionary
if(thisDict.writeToFile(docPath, atomically: true)){
NSLog("success")
} else {
NSLog("failure")
}
}
func getPlist(fileName:String)->Dictionary<String, AnyObject>{
let docsDir:String = dirPaths[0] as String
let docPath = docsDir + "/" + fileName
let thisDict = NSDictionary(contentsOfFile: docPath)
return thisDict! as! Dictionary<String, AnyObject>
}
这似乎是最不麻烦的读写方式,但让我的其余代码保持尽可能快。
斯威夫特5
如果你想获取某个键的特定值,那么我们可以使用下面的扩展,它使用Bundle上的infoDictionary属性。
可以使用Bundle.main.infoDictionary获取所有信息。在表单字典中plist值,因此我们可以直接使用Bundle上的object(forInfoDictionaryKey: key)方法查询
extension Bundle {
static func infoPlistValue(forKey key: String) -> Any? {
guard let value = Bundle.main.object(forInfoDictionaryKey: key) else {
return nil
}
return value
}
}
使用
guard let apiURL = Bundle.infoPlistValue(forKey: "API_URL_KEY") as? String else { return }
以下是我找到的解决方案:
let levelBlocks = NSDictionary(contentsOfFile: NSBundle.mainBundle().pathForResource("LevelBlocks", ofType: "plist"))
let test: AnyObject = levelBlocks.objectForKey("Level1")
println(test) // Prints the value of test
我将测试类型设置为AnyObject,以关闭关于可能发生的意外推断的警告。
而且,它必须在类方法中完成。
访问并保存已知类型的特定值:
let value = levelBlocks.objectForKey("Level1").objectForKey("amount") as Int
println(toString(value)) // Converts value to String and prints it
Swift -读写plist和文本文件....
override func viewDidLoad() {
super.viewDidLoad()
let fileManager = (NSFileManager .defaultManager())
let directorys : [String]? = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory,NSSearchPathDomainMask.AllDomainsMask, true) as? [String]
if (directorys != nil){
let directories:[String] = directorys!;
let dictionary = directories[0]; //documents directory
// Create and insert the data into the Plist file ....
let plistfile = "myPlist.plist"
var myDictionary: NSMutableDictionary = ["Content": "This is a sample Plist file ........."]
let plistpath = dictionary.stringByAppendingPathComponent(plistfile);
if !fileManager .fileExistsAtPath(plistpath){//writing Plist file
myDictionary.writeToFile(plistpath, atomically: false)
}
else{ //Reading Plist file
println("Plist file found")
let resultDictionary = NSMutableDictionary(contentsOfFile: plistpath)
println(resultDictionary?.description)
}
// Create and insert the data into the Text file ....
let textfile = "myText.txt"
let sampleText = "This is a sample text file ......... "
let textpath = dictionary.stringByAppendingPathComponent(textfile);
if !fileManager .fileExistsAtPath(textpath){//writing text file
sampleText.writeToFile(textpath, atomically: false, encoding: NSUTF8StringEncoding, error: nil);
} else{
//Reading text file
let reulttext = String(contentsOfFile: textpath, encoding: NSUTF8StringEncoding, error: nil)
println(reulttext)
}
}
else {
println("directory is empty")
}
}
我已经创建了一个简单的字典初始化器替换NSDictionary(contentsOfFile: path)。只要去掉NS。
extension Dictionary where Key == String, Value == Any {
public init?(contentsOfFile path: String) {
let url = URL(fileURLWithPath: path)
self.init(contentsOfURL: url)
}
public init?(contentsOfURL url: URL) {
guard let data = try? Data(contentsOf: url),
let dictionary = (try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [String: Any]) ?? nil
else { return nil }
self = dictionary
}
}
你可以这样使用它:
let filePath = Bundle.main.path(forResource: "Preferences", ofType: "plist")!
let preferences = Dictionary(contentsOfFile: filePath)!
UserDefaults.standard.register(defaults: preferences)
Swift 4.0 iOS 11.2.6列表解析和代码解析它,基于https://stackoverflow.com/users/3647770/ashok-r上面的答案。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>identity</key>
<string>blah-1</string>
<key>major</key>
<string>1</string>
<key>minor</key>
<string>1</string>
<key>uuid</key>
<string>f45321</string>
<key>web</key>
<string>http://web</string>
</dict>
<dict>
<key>identity</key>
<string></string>
<key>major</key>
<string></string>
<key>minor</key>
<string></string>
<key>uuid</key>
<string></string>
<key>web</key>
<string></string>
</dict>
</array>
</plist>
do {
let plistXML = try Data(contentsOf: url)
var plistData: [[String: AnyObject]] = [[:]]
var propertyListFormat = PropertyListSerialization.PropertyListFormat.xml
do {
plistData = try PropertyListSerialization.propertyList(from: plistXML, options: .mutableContainersAndLeaves, format: &propertyListFormat) as! [[String:AnyObject]]
} catch {
print("Error reading plist: \(error), format: \(propertyListFormat)")
}
} catch {
print("error no upload")
}