Wie bekomme ich eine Liste als Wörterbuch in Swift?

197

Ich spiele mit Apples neuer Programmiersprache Swift herum und habe einige Probleme ...

Derzeit versuche ich, eine Plist-Datei zu lesen. In Objective-C würde ich Folgendes tun, um den Inhalt als NSDictionary abzurufen:

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Config" ofType:@"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:filePath];

Wie bekomme ich eine Liste als Wörterbuch in Swift?

Ich gehe davon aus, dass ich den Weg zur Liste finden kann mit:

let path = NSBundle.mainBundle().pathForResource("Config", ofType: "plist")

Wenn dies funktioniert (Wenn es korrekt ist?): Wie erhalte ich den Inhalt als Wörterbuch?

Auch eine allgemeinere Frage:

Ist es in Ordnung, die Standard- NS * -Klassen zu verwenden? Ich denke schon ... oder fehlt mir etwas? Soweit ich weiß, sind die Standard-Framework- NS * -Klassen noch gültig und in Ordnung zu verwenden?

Sebastian
quelle
Die Antwort ist nicht mehr gültig. Könnten Sie bitte die Antwort des Ashok auswählen?
RodolfoAntonici

Antworten:

51

In schnellem 3.0 Lesen von Plist.

func readPropertyList() {
        var propertyListFormat =  PropertyListSerialization.PropertyListFormat.xml //Format of the Property List.
        var plistData: [String: AnyObject] = [:] //Our data
        let plistPath: String? = Bundle.main.path(forResource: "data", ofType: "plist")! //the path of the data
        let plistXML = FileManager.default.contents(atPath: plistPath!)!
        do {//convert the data to a dictionary and handle errors.
            plistData = try PropertyListSerialization.propertyList(from: plistXML, options: .mutableContainersAndLeaves, format: &propertyListFormat) as! [String:AnyObject]

        } catch {
            print("Error reading plist: \(error), format: \(propertyListFormat)")
        }
    }

Lesen Sie mehr SO VERWENDEN SIE EIGENTUMSLISTEN (.PLIST) IN SWIFT .

Ashok R.
quelle
Askok. Ich habe viele Stunden verloren, als ich heute versucht habe, eine Antwort darauf zu finden! DANKE!! Das hat perfekt funktioniert !!!
user3069232
281

Sie können NSDictionaries weiterhin in Swift verwenden:

Für Swift 4

 var nsDictionary: NSDictionary?
 if let path = Bundle.main.path(forResource: "Config", ofType: "plist") {
    nsDictionary = NSDictionary(contentsOfFile: path)
 }

Für Swift 3+

if let path = Bundle.main.path(forResource: "Config", ofType: "plist"),
   let myDict = NSDictionary(contentsOfFile: path){
    // Use your myDict here
}

Und ältere Versionen von Swift

var myDict: NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("Config", ofType: "plist") {
    myDict = NSDictionary(contentsOfFile: path)
}
if let dict = myDict {
    // Use your dict here
}

Die NSClasses sind weiterhin verfügbar und können problemlos in Swift verwendet werden. Ich denke, sie werden wahrscheinlich bald den Fokus auf schnell verlagern wollen, aber derzeit verfügen die schnellen APIs nicht über alle Funktionen der Kern-NSClasses.

Connor
quelle
hmm, wenn ich versuche, den von Ihnen angegebenen Code zu verwenden, erhalte ich die Fehlermeldung: xxx hat kein Mitglied namens dict
KennyVB
es funktioniert gut auf Spielplatz tho. nur nicht in meinem schnellen Dokument
KennyVB
Wie sieht es aus, wenn Array?
Arnlee Vizcayno
Sieht aus wie mainBundle()ist gerade mainin Swift 3
BallpointBen
8
Diese Antwort ist veraltet. Selbst in Swift 3 sollten Sie dasNSArray/NSDictionary Lesen von Eigenschaftslistendaten überhaupt nicht verwenden . PropertyListSerialization(und in Swift 4 alternativ das CodableProtokoll) ist die entsprechende API. Es bietet eine moderne Fehlerbehandlung und die Daten können direkt in native Swift-Sammlungstypen konvertiert werden.
Vadian
141

Folgendes mache ich, wenn ich eine .plist in ein Swift-Wörterbuch konvertieren möchte:

if let path = NSBundle.mainBundle().pathForResource("Config", ofType: "plist") {
  if let dict = NSDictionary(contentsOfFile: path) as? Dictionary<String, AnyObject> {
    // use swift dictionary as normal
  }
}

Bearbeitet für Swift 2.0:

if let path = NSBundle.mainBundle().pathForResource("Config", ofType: "plist"), dict = NSDictionary(contentsOfFile: path) as? [String: AnyObject] {
    // use swift dictionary as normal
}

Bearbeitet für Swift 3.0:

if let path = Bundle.main.path(forResource: "Config", ofType: "plist"), let dict = NSDictionary(contentsOfFile: path) as? [String: AnyObject] {
        // use swift dictionary as normal
}
pheedsta
quelle
3
Ich denke, dies ist die "richtigste" Antwort des Haufen, bis es einen nativen schnellen Weg gibt, dies zu tun.
DudeOnRock
1
Diese Antwort ist veraltet. In Swift 3 Sie sollten nicht verwenden , NSArray/NSDictionaryan allen Eigenschaftsliste Daten zu lesen. PropertyListSerialization(und in Swift 4 alternativ das CodableProtokoll) ist die entsprechende API. Es bietet eine moderne Fehlerbehandlung und die Daten können direkt in native Swift-Sammlungstypen konvertiert werden.
Vadian
47

Swift 4.0

Sie können jetzt das Decodable-Protokoll verwenden, um eine .plist in eine benutzerdefinierte Struktur zu decodieren. Ich werde ein grundlegendes Beispiel für kompliziertere .plist-Strukturen durchgehen, die ich zum Lesen von Decodable / Encodable empfehle (eine gute Ressource finden Sie hier: https://benscheirman.com/2017/06/swift-json/ ).

Richten Sie zuerst Ihre Struktur im Format Ihrer .plist-Datei ein. In diesem Beispiel werde ich eine .plist mit einem Wörterbuch auf Stammebene und 3 Einträgen betrachten: 1 String mit dem Schlüssel "name", 1 Int mit dem Schlüssel "age" und 1 Boolean mit dem Schlüssel "single". Hier ist die Struktur:

struct Config: Decodable {
    private enum CodingKeys: String, CodingKey {
        case name, age, single
    }

    let name: String
    let age: Int
    let single: Bool
}

Einfach genug. Nun der coole Teil. Mit der PropertyListDecoder-Klasse können wir die .plist-Datei einfach in eine Instanziierung dieser Struktur analysieren:

func parseConfig() -> Config {
    let url = Bundle.main.url(forResource: "Config", withExtension: "plist")!
    let data = try! Data(contentsOf: url)
    let decoder = PropertyListDecoder()
    return try! decoder.decode(Config.self, from: data)
}

Nicht viel mehr Code, um den man sich sorgen muss, und alles in Swift. Besser noch, wir haben jetzt eine Instanziierung der Konfigurationsstruktur, die wir leicht verwenden können:

let config = parseConfig()
print(config.name) 
print(config.age)
print(config.single) 

Dies druckt den Wert für die Schlüssel "Name", "Alter" und "Einzel" in der .plist.

ekreloff
quelle
1
Das ist die beste Antwort für Swift 4. Aber warum nicht Bundle.main.url(forResource: "Config", withExtension: "plist")und loswerden URL(fileURLWithPath? Und da die Datei vorhanden sein muss (zur Entwurfs- / Kompilierungszeit), können alle Werte zwangsweise entpackt werden. Der Code darf nicht abstürzen, wenn alles richtig gestaltet ist.
Vadian
@vadian Sicher können Sie verwenden url(forResource: "Config", withExtension: "plist")Ich habe nur verglichen, was die OP in ihrem Code als Vergleichspunkt getan hat. Was das Auspacken von Gewalt angeht, versuche ich, auf Nummer sicher zu gehen. Ich denke, das ist eine grundlegende Frage für Swift im Allgemeinen. Ich möchte lieber genau wissen, was mein Code in jeder Situation tut, als abstürzen.
Ekreloff
1) Bitte nehmen Sie keine schlechten Gewohnheiten an, wenn es eine geeignetere API gibt. 2) Dies ist einer der wenigen Fälle, in denen ein erzwungener Absturz einen Konstruktionsfehler entdeckt. Jede Datei im Bundle muss zur Kompilierungszeit vorhanden sein und kann zur Laufzeit nicht geändert werden, da alle Dateien mit Code signiert sind. Noch einmal: Der Code darf nicht abstürzen, wenn alles richtig gestaltet ist .
Vadian
Ja, du kennst dein Recht. Ich wusste nicht, dass dies bei Bundle-Ressourcen der Fall ist.
Ekreloff
2
@NaveenGeorgeThoppan Wenn Sie dieses Beispiel als Wörterbuch verwenden, ist es einfach decoder.decode([Config].self, from: data). (Beachten Sie die Klammern um [Config])
Ekreloff
22

Diese Antwort verwendet native Swift-Objekte anstelle von NSDictionary.

Swift 3.0

//get the path of the plist file
guard let plistPath = Bundle.main.path(forResource: "level1", ofType: "plist") else { return }
//load the plist as data in memory
guard let plistData = FileManager.default.contents(atPath: plistPath) else { return }
//use the format of a property list (xml)
var format = PropertyListSerialization.PropertyListFormat.xml
//convert the plist data to a Swift Dictionary
guard let  plistDict = try! PropertyListSerialization.propertyList(from: plistData, options: .mutableContainersAndLeaves, format: &format) as? [String : AnyObject] else { return }
//access the values in the dictionary 
if let value = plistDict["aKey"] as? String {
  //do something with your value
  print(value)
}
//you can also use the coalesce operator to handle possible nil values
var myValue = plistDict["aKey"] ?? ""
Tommie C.
quelle
Gibt es eine kurze Version dazu?
harsch_v
18

Ich habe mit Swift 3.0 gearbeitet und wollte eine Antwort auf die aktualisierte Syntax liefern. Zusätzlich und möglicherweise noch wichtiger ist, dass ich das PropertyListSerialization- Objekt verwende, um das schwere Heben durchzuführen. Dies ist viel flexibler als nur das NSDictionary, da es ein Array als Stammtyp der Plist zulässt.

Unten ist ein Screenshot der von mir verwendeten Plist. Es ist ein bisschen kompliziert, um die verfügbare Leistung zu zeigen, aber dies funktioniert für jede zulässige Kombination von Plistentypen.

Beispiel einer Plist-Datei Wie Sie sehen können, verwende ich ein Array von String: String-Wörterbüchern, um eine Liste von Website-Namen und deren entsprechende URL zu speichern.

Ich verwende das PropertyListSerialization- Objekt, wie oben erwähnt, um das schwere Heben für mich zu erledigen. Außerdem ist Swift 3.0 "Swifty" geworden, sodass alle Objektnamen das Präfix "NS" verloren haben.

let path = Bundle.main().pathForResource("DefaultSiteList", ofType: "plist")!
let url = URL(fileURLWithPath: path)
let data = try! Data(contentsOf: url)
let plist = try! PropertyListSerialization.propertyList(from: data, options: .mutableContainers, format: nil)

Nachdem der obige Code ausgeführt wurde plist, ist er vom Typ Array<AnyObject>, aber wir wissen, um welchen Typ es sich wirklich handelt, damit wir ihn in den richtigen Typ umwandeln können:

let dictArray = plist as! [[String:String]]
// [[String:String]] is equivalent to Array< Dictionary<String, String> >

Und jetzt können wir auf natürliche Weise auf die verschiedenen Eigenschaften unseres Array of String: String Dictionaries zugreifen. Hoffentlich um sie in tatsächlich stark typisierte Strukturen oder Klassen umzuwandeln;)

print(dictArray[0]["Name"])
Nick
quelle
8

Es ist am besten, native Wörterbücher und Arrays zu verwenden, da diese für die Verwendung mit Swift optimiert wurden. Davon abgesehen können Sie NS ... -Klassen schnell verwenden, und ich denke, diese Situation rechtfertigt dies. So würden Sie es implementieren:

var path = NSBundle.mainBundle().pathForResource("Config", ofType: "plist")
var dict = NSDictionary(contentsOfFile: path)

Bisher (meiner Meinung nach) ist dies der einfachste und effizienteste Weg, um auf eine Liste zuzugreifen. In Zukunft erwarte ich jedoch, dass Apple den nativen Wörterbüchern mehr Funktionen (z. B. die Verwendung der Liste) hinzufügt.

67cherries
quelle
Ist das Hinzufügen von Plistenlesungen zu einheimischen Wörterbüchern bereits geschehen, soweit Sie wissen?
SpacyRicochet
8

Swift - Lese- / Schreibliste und Textdatei ....

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")
    }
}
Nithin Sathyan
quelle
8

Swift 2.0: Zugriff auf Info.Plist

Ich habe ein Wörterbuch namens CoachMarksDictionary mit einem booleschen Wert in Info.Plist. Ich möchte auf den Bool-Wert zugreifen und ihn wahr machen.

let path = NSBundle.mainBundle().pathForResource("Info", ofType: "plist")!
  let dict = NSDictionary(contentsOfFile: path) as! [String: AnyObject]

  if let CoachMarksDict = dict["CoachMarksDictionary"] {
       print("Info.plist : \(CoachMarksDict)")

   var dashC = CoachMarksDict["DashBoardCompleted"] as! Bool
    print("DashBoardCompleted state :\(dashC) ")
  }

Schreiben an Plist:

Aus einer benutzerdefinierten Liste: - (Aus Datei-Neue-Datei-Ressourcen-Eigenschaftsliste erstellen. Drei Zeichenfolgen mit dem Namen hinzugefügt: DashBoard_New, DashBoard_Draft, DashBoard_Completed)

func writeToCoachMarksPlist(status:String?,keyName:String?)
 {
  let path1 = NSBundle.mainBundle().pathForResource("CoachMarks", ofType: "plist")
  let coachMarksDICT = NSMutableDictionary(contentsOfFile: path1!)! as NSMutableDictionary
  var coachMarksMine = coachMarksDICT.objectForKey(keyName!)

  coachMarksMine  = status
  coachMarksDICT.setValue(status, forKey: keyName!)
  coachMarksDICT.writeToFile(path1!, atomically: true)
 }

Die Methode kann als aufgerufen werden

self.writeToCoachMarksPlist(" true - means user has checked the marks",keyName: "the key in the CoachMarks dictionary").
AG
quelle
Darauf habe ich geachtet! Danke Kumpel!
Jayprakash Dubey
6

Über Nicks Antwort in eine Convenience-Erweiterung umgewandelt:

extension Dictionary {
    static func contentsOf(path: URL) -> Dictionary<String, AnyObject> {
        let data = try! Data(contentsOf: path)
        let plist = try! PropertyListSerialization.propertyList(from: data, options: .mutableContainers, format: nil)

        return plist as! [String: AnyObject]
    }
}

Verwendung:

let path = Bundle.main.path(forResource: "plistName", ofType: "plist")!
let url = URL(fileURLWithPath: path)
let dict = Dictionary<String, AnyObject>.contentsOf(path: url)

Ich würde wetten, dass es auch funktionieren würde, eine ähnliche Erweiterung für Arrays zu erstellen

mredig
quelle
5

kann es tatsächlich in 1 Zeile tun

    var dict = NSDictionary(contentsOfFile: NSBundle.mainBundle().pathForResource("Config", ofType: "plist"))
KennyVB
quelle
5

Sie können plist in SWIFT-Sprache folgendermaßen lesen:

let path = NSBundle.mainBundle().pathForResource("PriceList", ofType: "plist")
let dict = NSDictionary(contentsOfFile: path)

Wert des einzelnen Wörterbuchs lesen:

let test: AnyObject = dict.objectForKey("index1")

Wenn Sie ein vollständiges mehrdimensionales Wörterbuch in plist erhalten möchten:

let value: AnyObject = dict.objectForKey("index2").objectForKey("date")

Hier ist die Liste:

<plist version="1.0">
<dict>
<key>index2</key>
<dict>
    <key>date</key>
    <string>20140610</string>
    <key>amount</key>
    <string>110</string>
</dict>
<key>index1</key>
<dict>
    <key>amount</key>
    <string>125</string>
    <key>date</key>
    <string>20140212</string>
</dict>
</dict>
</plist>
imti
quelle
4

Da diese Antwort noch nicht hier ist, möchten Sie nur darauf hinweisen, dass Sie auch die infoDictionary-Eigenschaft verwenden können, um die Info-Liste als Wörterbuch abzurufen Bundle.main.infoDictionary.

Obwohl so etwas Bundle.main.object(forInfoDictionaryKey: kCFBundleNameKey as String) möglicherweise schneller ist, wenn Sie nur an einem bestimmten Element in der Info-Liste interessiert sind.

// Swift 4

// Getting info plist as a dictionary
let dictionary = Bundle.main.infoDictionary

// Getting the app display name from the info plist
Bundle.main.infoDictionary?[kCFBundleNameKey as String]

// Getting the app display name from the info plist (another way)
Bundle.main.object(forInfoDictionaryKey: kCFBundleNameKey as String)
Scott Marchant
quelle
3

In meinem Fall erstelle ich einen NSDictionaryangerufenen appSettingsund füge alle benötigten Schlüssel hinzu. Für diesen Fall lautet die Lösung:

if let dict = NSBundle.mainBundle().objectForInfoDictionaryKey("appSettings") {
  if let configAppToken = dict["myKeyInsideAppSettings"] as? String {

  }
}
jose920405
quelle
Vielen Dank. objectForInfoDictionaryKeywar genau das, wonach ich gesucht habe.
LunaCodeGirl
2

Sie können das verwenden, ich erstelle eine einfache Erweiterung für Dictionary in github https://github.com/DaRkD0G/LoadExtension

extension Dictionary {
    /**
        Load a Plist file from the app bundle into a new dictionary

        :param: File name
        :return: Dictionary<String, AnyObject>?
    */
    static func loadPlistFromProject(filename: String) -> Dictionary<String, AnyObject>? {

        if let path = NSBundle.mainBundle().pathForResource("GameParam", ofType: "plist") {
            return NSDictionary(contentsOfFile: path) as? Dictionary<String, AnyObject>
        }
        println("Could not find file: \(filename)")
        return nil
    }
}

Und Sie können das zum Laden verwenden

/**
  Example function for load Files Plist

  :param: Name File Plist
*/
func loadPlist(filename: String) -> ExampleClass? {
    if let dictionary = Dictionary<String, AnyObject>.loadPlistFromProject(filename) {
        let stringValue = (dictionary["name"] as NSString)
        let intergerValue = (dictionary["score"] as NSString).integerValue
        let doubleValue = (dictionary["transition"] as NSString).doubleValue

        return ExampleClass(stringValue: stringValue, intergerValue: intergerValue, doubleValue: doubleValue)
    }
    return nil
}
YannSteph
quelle
2

Hier ist eine etwas kürzere Version, basierend auf der Antwort von @connor

guard let path = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist"),
    let myDict = NSDictionary(contentsOfFile: path) else {
    return nil
}

let value = dict.value(forKey: "CLIENT_ID") as! String?
Bence Pattogato
quelle
2

Swift 3.0

if let path = Bundle.main.path(forResource: "config", ofType: "plist") {
    let dict = NSDictionary(contentsOfFile: path)

    // use dictionary
}

Der einfachste Weg dies meiner Meinung nach zu tun.

sehr schön
quelle
2

Ich habe einen einfachen DictionaryInitialisierer erstellt, der ersetzt NSDictionary(contentsOfFile: path). Entfernen Sie einfach die 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
    }

}

Sie können es so verwenden:

let filePath = Bundle.main.path(forResource: "Preferences", ofType: "plist")!
let preferences = Dictionary(contentsOfFile: filePath)!
UserDefaults.standard.register(defaults: preferences)
Jordan H.
quelle
2

Swift 4.0 iOS 11.2.6-Liste analysiert und Code zum Parsen, basierend auf der obigen Antwort 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")
    }
user3069232
quelle
1

Schritt 1 : Einfache und schnellste Methode zum Parsen von Plist in Swift 3+

extension Bundle {

    func parsePlist(ofName name: String) -> [String: AnyObject]? {

        // check if plist data available
        guard let plistURL = Bundle.main.url(forResource: name, withExtension: "plist"),
            let data = try? Data(contentsOf: plistURL)
            else {
                return nil
        }

        // parse plist into [String: Anyobject]
        guard let plistDictionary = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [String: AnyObject] else {
            return nil
        }

        return plistDictionary
    }
}

Schritt 2: Verwendung:

Bundle().parsePlist(ofName: "Your-Plist-Name")
Bhuvan Bhatt
quelle
0

Hier ist die Lösung, die ich gefunden habe:

let levelBlocks = NSDictionary(contentsOfFile: NSBundle.mainBundle().pathForResource("LevelBlocks", ofType: "plist"))
let test: AnyObject = levelBlocks.objectForKey("Level1")
println(test) // Prints the value of test

Ich habe den Typ testso eingestellt AnyObject, dass eine Warnung vor einer unerwarteten Schlussfolgerung, die auftreten kann , zum Schweigen gebracht wird.

Es muss auch in einer Klassenmethode durchgeführt werden.

So greifen Sie auf einen bestimmten Wert eines bekannten Typs zu und speichern ihn:

let value = levelBlocks.objectForKey("Level1").objectForKey("amount") as Int
println(toString(value)) // Converts value to String and prints it
TheAppleMan
quelle
0

Ich verwende schnelle Wörterbücher, konvertiere sie jedoch in und aus NSDictionaries in meiner Dateimanager-Klasse wie folgt:

    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>
    }

Dies scheint die am wenigsten problematische Art zu lesen und zu schreiben, aber lassen Sie uns den Rest meines Codes so schnell wie möglich bleiben.

ew parris
quelle
0

Plist ist eine einfache Swift-Aufzählung, die ich für die Arbeit mit Eigenschaftslisten erstellt habe.

// load an applications info.plist data

let info = Plist(NSBundle.mainBundle().infoDictionary)
let identifier = info["CFBundleIndentifier"].string!

Mehr Beispiele:

import Plist

// initialize using an NSDictionary
// and retrieve keyed values

let info = Plist(dict)
let name = info["name"].string ?? ""
let age = info["age"].int ?? 0


// initialize using an NSArray
// and retrieve indexed values

let info = Plist(array)
let itemAtIndex0 = info[0].value


// utility initiaizer to load a plist file at specified path
let info = Plist(path: "path_to_plist_file")

// we support index chaining - you can get to a dictionary from an array via
// a dictionary and so on
// don't worry, the following will not fail with errors in case
// the index path is invalid
if let complicatedAccessOfSomeStringValueOfInterest = info["dictKey"][10]["anotherKey"].string {
  // do something
}
else {
  // data cannot be indexed
}

// you can also re-use parts of a plist data structure

let info = Plist(...)
let firstSection = info["Sections"][0]["SectionData"]
let sectionKey = firstSection["key"].string!
let sectionSecret = firstSection["secret"].int!

Plist.swift

Plist selbst ist recht einfach. Hier ist die Auflistung für den Fall, dass Sie direkt darauf verweisen.

//
//  Plist.swift
//


import Foundation


public enum Plist {

    case dictionary(NSDictionary)
    case Array(NSArray)
    case Value(Any)
    case none

    public init(_ dict: NSDictionary) {
        self = .dictionary(dict)
    }

    public init(_ array: NSArray) {
        self = .Array(array)
    }

    public init(_ value: Any?) {
        self = Plist.wrap(value)
    }

}


// MARK:- initialize from a path

extension Plist {

    public init(path: String) {
        if let dict = NSDictionary(contentsOfFile: path) {
            self = .dictionary(dict)
        }
        else if let array = NSArray(contentsOfFile: path) {
            self = .Array(array)
        }
        else {
            self = .none
        }
    }

}


// MARK:- private helpers

extension Plist {

    /// wraps a given object to a Plist
    fileprivate static func wrap(_ object: Any?) -> Plist {

        if let dict = object as? NSDictionary {
            return .dictionary(dict)
        }
        if let array = object as? NSArray {
            return .Array(array)
        }
        if let value = object {
            return .Value(value)
        }
        return .none
    }

    /// tries to cast to an optional T
    fileprivate func cast<T>() -> T? {
        switch self {
        case let .Value(value):
            return value as? T
        default:
            return nil
        }
    }
}

// MARK:- subscripting

extension Plist {

    /// index a dictionary
    public subscript(key: String) -> Plist {
        switch self {

        case let .dictionary(dict):
            let v = dict.object(forKey: key)
            return Plist.wrap(v)

        default:
            return .none
        }
    }

    /// index an array
    public subscript(index: Int) -> Plist {
        switch self {
        case let .Array(array):
            if index >= 0 && index < array.count {
                return Plist.wrap(array[index])
            }
            return .none

        default:
            return .none
        }
    }

}


// MARK:- Value extraction

extension Plist {

    public var string: String?       { return cast() }
    public var int: Int?             { return cast() }
    public var double: Double?       { return cast() }
    public var float: Float?         { return cast() }
    public var date: Date?         { return cast() }
    public var data: Data?         { return cast() }
    public var number: NSNumber?     { return cast() }
    public var bool: Bool?           { return cast() }


    // unwraps and returns the underlying value
    public var value: Any? {
        switch self {
        case let .Value(value):
            return value
        case let .dictionary(dict):
            return dict
        case let .Array(array):
            return array
        case .none:
            return nil
        }
    }

    // returns the underlying array
    public var array: NSArray? {
        switch self {
        case let .Array(array):
            return array
        default:
            return nil
        }
    }

    // returns the underlying dictionary
    public var dict: NSDictionary? {
        switch self {
        case let .dictionary(dict):
            return dict
        default:
            return nil
        }
    }

}


// MARK:- CustomStringConvertible

extension Plist : CustomStringConvertible {
    public var description:String {
        switch self {
        case let .Array(array): return "(array \(array))"
        case let .dictionary(dict): return "(dict \(dict))"
        case let .Value(value): return "(value \(value))"
        case .none: return "(none)"
        }
    }
}
Benzi
quelle
0

Swift 3.0

Wenn Sie ein "2-dimensionales Array" aus .plist lesen möchten, können Sie es folgendermaßen versuchen:

if let path = Bundle.main.path(forResource: "Info", ofType: "plist") {
    if let dimension1 = NSDictionary(contentsOfFile: path) {
        if let dimension2 = dimension1["key"] as? [String] {
            destination_array = dimension2
        }
    }
}
Sandu
quelle
-2

Einfache Struktur für den Zugriff auf die Plist-Datei (Swift 2.0)

struct Configuration {      
  static let path = NSBundle.mainBundle().pathForResource("Info", ofType: "plist")!
  static let dict = NSDictionary(contentsOfFile: path) as! [String: AnyObject]

  static let someValue = dict["someKey"] as! String
}

Verwendung:

print("someValue = \(Configuration.someValue)")
n0_quarter
quelle