Bagaimana cara mendapatkan plist sebagai Kamus di Swift?


197

Saya bermain-main dengan bahasa pemrograman Swift baru Apple dan memiliki beberapa masalah ...

Saat ini saya mencoba membaca file plist, di Objective-C saya akan melakukan yang berikut untuk mendapatkan konten sebagai NSDictionary:

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

Bagaimana cara mendapatkan plist sebagai Kamus di Swift?

Saya berasumsi saya bisa mendapatkan path ke plist dengan:

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

Kapan ini berfungsi (Jika itu benar?): Bagaimana saya mendapatkan konten sebagai Kamus?

Juga pertanyaan yang lebih umum:

Apakah boleh menggunakan kelas NS * default ? Saya kira begitu ... atau saya melewatkan sesuatu? Sejauh yang saya tahu kerangka kerja standar NS * kelas masih valid dan boleh digunakan?


Jawabannya tidak lagi valid, bisakah Anda memilih jawaban Ashok?
RodolfoAntonici

Jawaban:


51

Dalam 3,0 Membaca cepat dari 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)")
        }
    }

Baca Selengkapnya CARA MENGGUNAKAN DAFTAR PROPERTI (. DAFTAR) DI SWIFT .


Askok. Hilang berjam-jam mencoba menemukan jawaban untuk ini hari ini di ini! TERIMA KASIH!! Ini bekerja dengan sempurna !!!
user3069232

281

Anda masih dapat menggunakan NSDictionaries di Swift:

Untuk Swift 4

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

Untuk Swift 3+

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

Dan versi Swift yang lebih lama

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

NSClasses masih tersedia dan sangat baik untuk digunakan di Swift. Saya pikir mereka mungkin ingin segera beralih fokus ke swift, tetapi saat ini API cepat tidak memiliki semua fungsionalitas NSClasses inti.


hmm ketika saya mencoba menggunakan kode yang Anda berikan, saya mendapatkan kesalahan: xxx tidak memiliki anggota bernama dict
KennyVB

itu berfungsi dengan baik di taman bermain tho. tidak dalam dokumen cepat saya
KennyVB

bagaimana jadinya jika Array?
Arnlee Vizcayno

Sepertinya mainBundle()hanya ada maindi Swift 3
BallpointBen

8
Jawaban ini sudah usang. Bahkan di Swift 3 Anda tidak boleh menggunakan NSArray/NSDictionarysama sekali untuk membaca data daftar properti. PropertyListSerialization(dan dalam Swift 4 sebagai alternatif Codableprotokol) adalah API yang sesuai. Ini memberikan penanganan kesalahan modern dan data dapat dikonversi langsung ke tipe pengumpulan Swift asli.
vadian

141

Ini yang saya lakukan jika saya ingin mengonversi .plist ke kamus Swift:

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

Diedit untuk Swift 2.0:

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

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

3
Saya pikir ini adalah jawaban "yang paling benar" dari kelompok itu sampai ada cara cepat asli untuk melakukan ini.
DudeOnRock

1
Jawaban ini sudah usang. Di Swift 3 Anda tidak boleh menggunakan NSArray/NSDictionarysama sekali untuk membaca data daftar properti. PropertyListSerialization(dan dalam Swift 4 sebagai alternatif Codableprotokol) adalah API yang sesuai. Ini memberikan penanganan kesalahan modern dan data dapat dikonversi langsung ke tipe pengumpulan Swift asli.
vadian

47

Cepat 4.0

Anda sekarang dapat menggunakan protokol Decodable untuk Decode a .plist ke kustom struct. Saya akan membahas contoh dasar, untuk struktur .plist yang lebih rumit Saya sarankan membaca di Decodable / Encodable (sumber yang bagus ada di sini: https://benscheirman.com/2017/06/swift-json/ ).

Pertama, atur struct Anda ke dalam format file .plist Anda. Untuk contoh ini saya akan mempertimbangkan. Daftar dengan Kamus tingkat akar dan 3 entri: 1 String dengan kunci "nama", 1 Int dengan kunci "usia", dan 1 Boolean dengan kunci "tunggal". Berikut adalah struct:

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

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

Cukup sederhana. Sekarang bagian yang keren. Menggunakan kelas PropertyListDecoder kita dapat dengan mudah mem-parsing file .plist ke instantiation dari struct ini:

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

Tidak banyak lagi kode yang perlu dikhawatirkan, dan semuanya ada di Swift. Lebih baik lagi sekarang kita memiliki instantiation dari struct Config yang dapat kita gunakan dengan mudah:

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

Ini Mencetak nilai untuk kunci "nama", "usia", dan "tunggal" di .plist.


1
Itu jawaban terbaik untuk Swift 4. Tapi mengapa tidak Bundle.main.url(forResource: "Config", withExtension: "plist")dan singkirkan URL(fileURLWithPath? Dan karena file harus ada (pada desain / waktu kompilasi) semua nilai dapat dibuka paksa. Kode tidak boleh macet jika semuanya dirancang dengan benar.
vadian

@vadian Tentu Anda dapat menggunakan url(forResource: "Config", withExtension: "plist")saya hanya mencocokkan apa yang OP lakukan dalam kode mereka sebagai titik perbandingan. Sejauh memaksa membuka semuanya, saya mencoba berbuat salah di sisi kehati-hatian. Saya pikir itu adalah pertanyaan mendasar bagi Swift secara umum. Saya lebih suka tahu persis apa yang kode saya akan lakukan dalam situasi apa pun selain crash.
ekreloff

1) Tolong jangan mengadopsi kebiasaan buruk jika ada API yang lebih tepat. 2) Itu salah satu dari beberapa kasus di mana crash paksa menemukan kesalahan desain. File apa pun dalam bundel harus ada pada waktu kompilasi dan tidak dapat diubah saat runtime karena semua file ditandatangani kode. Sekali lagi: Kode tidak boleh macet jika semuanya dirancang dengan benar .
vadian

Ya, Anda tahu hak Anda. Tidak menyadari bahwa itulah yang terjadi dengan sumber daya Bundle.
ekreloff

2
@NaveenGeorgeThoppan jika Anda menggunakan contoh ini sebagai kamus Anda maka itu akan menjadi sederhana decoder.decode([Config].self, from: data). (Perhatikan tanda kurung di sekitar [Konfigurasi])
ekreloff

22

Jawaban ini menggunakan objek asli Swift daripada 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"] ?? ""

Apakah ada versi ringkas untuk ini?
harsh_v

18

Saya telah bekerja dengan Swift 3.0 dan ingin menyumbangkan jawaban untuk sintaks yang diperbarui. Selain itu, dan mungkin yang lebih penting, saya menggunakan PropertyListSerialization objek untuk melakukan angkat berat, yang jauh lebih fleksibel daripada hanya menggunakan NSDictionary karena memungkinkan untuk Array sebagai jenis akar dari plist.

Di bawah ini adalah screenshot dari plist yang saya gunakan. Ini adalah sedikit rumit, sehingga untuk menunjukkan kekuatan yang tersedia, tetapi ini akan bekerja untuk setiap kombinasi yang diijinkan jenis plist.

Contoh file plist Seperti yang Anda lihat, saya menggunakan Array String: kamus string untuk menyimpan daftar nama situs web dan URL yang sesuai.

Saya menggunakan objek PropertyListSerialization , seperti yang disebutkan di atas, untuk melakukan angkat berat bagi saya. Selain itu, Swift 3.0 telah menjadi lebih "Swifty" sehingga semua nama objek telah kehilangan awalan "NS".

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)

Setelah kode di atas berjalan plistakan menjadi tipe Array<AnyObject>, tetapi kita tahu tipe apa itu sebenarnya sehingga kita dapat melemparkannya ke tipe yang benar:

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

Dan sekarang kita dapat mengakses berbagai properti Array String kami: Kamus String dengan cara alami. Mudah-mudahan untuk mengubahnya menjadi struct atau kelas yang sangat diketik nyata;)

print(dictArray[0]["Name"])

8

Cara terbaik adalah menggunakan kamus dan array asli karena kamus tersebut telah dioptimalkan untuk digunakan dengan cepat. Yang sedang berkata Anda dapat menggunakan NS ... kelas di cepat dan saya pikir situasi ini menjamin itu. Inilah cara Anda mengimplementasikannya:

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

Sejauh ini (menurut saya) ini adalah cara termudah dan paling efisien untuk mengakses sebuah plist, tetapi di masa depan saya berharap apel akan menambah lebih banyak fungsi (seperti menggunakan plist) ke dalam kamus asli.


Sejauh yang Anda tahu, sudahkah menambahkan membaca plist ke kamus asli sudah terjadi?
SpacyRicochet

8

Swift - Baca / Tulis plist dan file teks ....

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

8

Swift 2.0: Mengakses Info.Plist

Saya memiliki Kamus bernama CoachMarksDictionary dengan nilai boolean di Info.Plist. Saya ingin mengakses nilai bool dan mewujudkannya.

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

Menulis Kepada Plist:

Dari Custom Plist: - (Buat dari File-New-File-Resource-PropertyList. Menambahkan tiga string bernama: 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)
 }

Metode ini dapat disebut sebagai

self.writeToCoachMarksPlist(" true - means user has checked the marks",keyName: "the key in the CoachMarks dictionary").

Inilah yang saya cari! Terimakasih kawan!
Jayprakash Dubey

6

Dikonversi menjadi ekstensi kenyamanan melalui jawaban Nick:

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

pemakaian:

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

Saya berani bertaruh bahwa itu juga akan berhasil untuk membuat ekstensi serupa untuk Array


5

sebenarnya bisa melakukannya dalam 1 baris

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

5

Anda dapat membaca plist dalam Bahasa SWIFT dengan cara ini:

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

Baca nilai Kamus Tunggal:

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

Jika Anda ingin mendapatkan kamus multi-dimensi penuh dalam daftar:

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

Berikut adalah daftar:

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

5

Karena jawaban ini belum ada di sini, hanya ingin menunjukkan Anda juga dapat menggunakan properti infoDictionary untuk mendapatkan info daftar sebagai kamus Bundle.main.infoDictionary,.

Meskipun sesuatu seperti Bundle.main.object(forInfoDictionaryKey: kCFBundleNameKey as String) mungkin lebih cepat jika Anda hanya tertarik pada item tertentu dalam daftar info.

// 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)

3

dalam kasus saya saya membuat NSDictionarydisebut appSettingsdan menambahkan semua kunci yang diperlukan. Untuk kasus ini, solusinya adalah:

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

  }
}

Terima kasih. objectForInfoDictionaryKeypersis apa yang saya cari.
LunaCodeGirl

2

Anda dapat menggunakannya, saya membuat ekstensi sederhana untuk Kamus di 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
    }
}

Dan Anda dapat menggunakannya untuk memuat

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

2

Ini adalah versi yang sedikit lebih pendek, berdasarkan jawaban @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?

2

Swift 3.0

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

    // use dictionary
}

Cara termudah untuk melakukan ini menurut saya.


2

Saya telah membuat Dictionarypenginisialisasi sederhana yang menggantikan NSDictionary(contentsOfFile: path). Hapus saja 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
    }

}

Anda dapat menggunakannya seperti ini:

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

2

Swift 4.0 iOS 11.2.6 daftar diuraikan dan kode untuk menguraikannya, berdasarkan https://stackoverflow.com/users/3647770/ashok-r jawaban di atas.

<?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")
    }

1

Langkah 1 : Cara sederhana dan tercepat untuk mengurai plist di 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
    }
}

Langkah 2: Cara menggunakan:

Bundle().parsePlist(ofName: "Your-Plist-Name")

0

Inilah solusi yang saya temukan:

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

Saya mengatur jenis testkeAnyObject membungkam peringatan tentang kesimpulan yang tak terduga yang bisa terjadi.

Juga, itu harus dilakukan dalam metode kelas.

Untuk mengakses dan menyimpan nilai spesifik dari tipe yang dikenal:

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

0

Saya menggunakan kamus cepat tetapi mengonversinya ke dan dari NSDictionaries di kelas manajer file saya seperti:

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

Ini sepertinya cara yang paling tidak bermasalah untuk membaca dan menulis tetapi mari sisa kode saya tetap secepat mungkin.


0

Plist adalah enum Swift sederhana yang saya buat untuk bekerja dengan daftar properti.

// load an applications info.plist data

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

Lebih banyak contoh:

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 itu sendiri cukup sederhana, ini daftarnya jika Anda merujuk langsung.

//
//  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)"
        }
    }
}

0

Swift 3.0

jika Anda ingin membaca "Array 2-dimensi" dari .plist, Anda dapat mencobanya seperti ini:

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

-2

Struct sederhana untuk mengakses file plist (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
}

Pemakaian:

print("someValue = \(Configuration.someValue)")
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.