Swift'te Sözlük olarak nasıl plist edinebilirim?


198

Apple'ın yeni Swift programlama dili ile oynuyorum ve bazı problemlerim var ...

Şu anda bir plist dosyasını okumaya çalışıyorum, Objective-C içeriği NSDictionary olarak almak için aşağıdakileri yaparım:

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

Swift'te Sözlük olarak nasıl plist edinebilirim?

Ben plist yolu alabilirim varsayalım:

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

Bu işe yaradığında (Doğruysa?): İçeriği Sözlük olarak nasıl alabilirim?

Ayrıca daha genel bir soru:

Varsayılan NS * sınıflarını kullanmak uygun mudur? Sanırım ... yoksa bir şey mi kaçırıyorum? Bildiğim kadarıyla varsayılan çerçeve NS * sınıfları hala geçerli ve kullanmak için uygundur?


Cevap artık geçerli değil, lütfen Ashok'un cevabını seçer misiniz?
RodolfoAntonici

Yanıtlar:


52

Gelen Swift 3.0 PLIST dan Okuma.

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

Devamını Oku SWIFT'TE EMLAK LİSTELERİ (.PLIST) NASIL KULLANILIR .


Askok. Bugün bu konuda bir cevap bulmaya çalışırken saatlerce kaybetti! TEŞEKKÜR EDERİM!! Bu mükemmel çalıştı !!!
user3069232

282

Swift'te hala NSDictionaries kullanabilirsiniz:

Swift 4 için

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

Swift 3+ için

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

Ve Swift'in eski sürümleri

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 hala Swift'te mevcut ve mükemmel derecede iyi. Sanırım muhtemelen yakında odaklanmak için odağı kaydırmak isteyecekler, ancak şu anda hızlı API'ler çekirdek NSClasses'ın tüm işlevlerine sahip değil.


i sağlanan bu kodu kullanmayı deneyin ne zaman hmm i hatayı alıyorum: xxx üye adında dicti yok
KennyVB

tho oyun alanında iyi çalışıyor. benim hızlı
belgemde

Array nasıl görünüyor?
Arnlee Vizcayno

Görünüşe göre mainBundle()olduğunu sadece mainSwift 3
BallpointBen

9
Bu cevap eski. Swift 3'te bile özellik listesi verilerini okumak için hiç kullanmamalısınız NSArray/NSDictionary. PropertyListSerialization(ve Swift 4'te alternatif olarak Codableprotokol) uygun API'dir. Modern hata işleme sağlar ve veriler doğrudan yerel Swift toplama türlerine dönüştürülebilir.
vadian

141

Bir .plist'i Swift sözlüğüne dönüştürmek istersem bunu yaparım:

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

Swift 2.0 için düzenlendi:

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

Swift 3.0 için düzenlendi:

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

3
Bunu yapmanın yerel hızlı bir yolu olana kadar bu grubun "en doğru" cevabı olduğunu düşünüyorum.
DudeOnRock

1
Bu cevap eski. Swift 3'te özellik listesi verilerini okumak için hiç kullanmamalısınız NSArray/NSDictionary. PropertyListSerialization(ve Swift 4'te alternatif olarak Codableprotokol) uygun API'dir. Modern hata işleme sağlar ve veriler doğrudan yerel Swift toplama türlerine dönüştürülebilir.
vadian

47

Swift 4.0

Artık bir .plist dosyasını özel bir yapıda Kod Çözmek için Decodable protokolünü kullanabilirsiniz. Ben daha karmaşık .plist yapıları için Decodable / Encodable (daha iyi bir kaynak burada: https://benscheirman.com/2017/06/swift-json/ ) okumanızı tavsiye ederim .

Önce yapınızı .plist dosyanızın biçimine ayarlayın. Bu örnekte, bir kök düzeyi sözlüğü olan bir .plist ve 3 giriş düşüneceğim: 1 "name" anahtarlı dize, "age" anahtarlı 1 Int ve "single" anahtarlı 1 Boolean. İşte yapı:

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

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

Yeterince basit. Şimdi havalı kısım. PropertyListDecoder sınıfını kullanarak .plist dosyasını bu yapının örneğine kolayca ayrıştırabiliriz:

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

Endişelenecek daha fazla kod yok ve hepsi Swift'te. Daha da iyisi, şimdi kolayca yapılandırabileceğimiz Config yapısının bir örneğine sahibiz:

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

Bu, .plist'deki "ad", "yaş" ve "tek" tuşların değerini yazdırır.


1
Swift 4 için en iyi cevap bu. Ama neden olmasın Bundle.main.url(forResource: "Config", withExtension: "plist")ve kurtulun URL(fileURLWithPath? Ve dosyanın (tasarım / derleme zamanında) bulunması gerektiğinden, tüm değerler açılmaya zorlanabilir. Her şey düzgün bir şekilde tasarlanmışsa kod çökmemelidir.
vadian

@vadian kullanabilirsiniz Tabii url(forResource: "Config", withExtension: "plist")ben sadece OP bir karşılaştırma noktası olarak kendi kodunda ne yaptığını eşleşiyordu. Her şeyi açığa çıkaran kuvvet kadar, dikkatli olunca hata yapmaya çalışıyorum. Bunun genel olarak Swift için temel bir soru olduğunu düşünüyorum. Kodumun herhangi bir durumda kilitlenmeden ne yapacağını tam olarak bilmek isterim.
ekreloff

1) Daha uygun bir API varsa lütfen kötü alışkanlıkları benimsemeyin. 2) Zorla kilitlenmenin bir tasarım hatası bulduğu birkaç durumdan biri budur. Paketteki herhangi bir dosyanın derleme zamanında bulunması gerekir ve tüm dosyalar kod imzalı olduğu için çalışma zamanında değiştirilemez. Bir kez daha: Her şey düzgün tasarlanmışsa kod çökmemelidir .
vadian

Evet, hakkını biliyorsun. Bundle kaynaklarında bunun böyle olduğunu fark etmemiştim.
ekreloff

2
@NaveenGeorgeThoppan bu örneği sözlüğünüz olarak kullanırsanız, basitçe olur decoder.decode([Config].self, from: data). ([Yapılandırma] etrafındaki köşeli parantezlere dikkat edin)
ekreloff

22

Bu yanıt NSDictionary yerine Swift yerel nesnelerini kullanır.

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"] ?? ""

Bunun kısa bir versiyonu var mı?
harsh_v

19

Swift 3.0 ile çalışıyorum ve güncellenmiş sözdizimi için bir cevap vermek istedim. Ayrıca ve muhtemelen daha da önemlisi, plist kök türü olarak bir dizi için izin verir gibi sadece NSDictionary kullanmak çok daha esnek olan ağır kaldırma yapmak için PropertyListSerialization nesne kullanıyorum.

Aşağıda kullandığım plist'in bir ekran görüntüsü var. Bu bir olan küçük güç mevcut göstermek için, ancak bu plist türlerinin herhangi izin verilen kombinasyon için çalışacak böylece, karmaşık.

Örnek plist dosyası Gördüğünüz gibi, bir dizi web sitesi adı ve ilgili URL'lerini saklamak için Dizi Dizisi: String sözlükleri kullanıyorum.

Benim için ağır kaldırma yapmak için yukarıda belirtildiği gibi PropertyListSerialization nesne kullanıyorum . Ayrıca, Swift 3.0 daha "Swifty" haline geldi, bu nedenle tüm nesne adları "NS" önekini kaybetti.

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)

Yukarıdaki kod çalıştırmalarından sonra plisttür olacak Array<AnyObject>, ancak gerçekten ne tür olduğunu biliyoruz, böylece doğru türe atabiliriz:

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

Ve şimdi Dizi Dizisi: String Sözlüklerimizin çeşitli özelliklerine doğal bir şekilde erişebiliriz. Umarım onları güçlü bir şekilde yazılmış yapılara veya sınıflara dönüştürmek;)

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

8

Yerel sözlükleri ve dizileri kullanmak en iyisidir çünkü bunlar hızlı bir şekilde kullanılmak üzere optimize edilmiştir. NS ... sınıflarını hızlı bir şekilde kullanabileceğiniz söyleniyor ve bence bu durum bunu garanti ediyor. Bunu nasıl uygulayacağınız aşağıda açıklanmıştır:

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

Şimdiye kadar (bence) bu bir plist'e erişmenin en kolay ve etkili yoludur, ancak gelecekte elmanın yerel sözlüklere daha fazla işlevsellik (plist kullanmak gibi) ekleyeceğini umuyorum.


Bildiğiniz kadarıyla, yerel sözlüklere plist okuma eklemek zaten oldu mu?
SpacyRicochet

8

Swift - Okuma ve yazma plist ve metin dosyası ....

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: Info.Plist'e Erişim

Info.Plist boole değeri olan CoachMarksDictionary adlı bir sözlük var. Bool değerine erişmek ve doğru yapmak istiyorum.

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

Listeye Yazmak:

Özel Listeden: - (Dosya-Yeni-Dosya-Kaynak-Özellik Listesinden Yap. DashBoard_New, DashBoard_Draft, DashBoard_Completed adlı üç dize eklendi)

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

Yöntem şu şekilde adlandırılabilir:

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

Aradığım şey buydu! Sağol kanka!
Jayprakash Dubey

6

Nick'in cevabı ile kolaylık uzantısına dönüştürüldü:

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

kullanımı:

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

Diziler için benzer bir uzantı oluşturmanın da işe yarayacağına bahse girmeye hazırım


5

aslında 1 satırda yapabilir

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

5

PLIF'i SWIFT Dili'nde şu şekilde okuyabilirsiniz:

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

Tek Sözlük değerini oku:

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

Plisteki tam çok boyutlu sözlüğü almak istiyorsanız:

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

İşte plist:

<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

Bu cevap henüz burada olmadığından, bilgi plistini sözlük olarak almak için infoDictionary özelliğini de kullanabileceğinizi belirtmek istedim Bundle.main.infoDictionary.

Ancak , bilgi plisteki belirli bir öğeyle ilgileniyorsanız, benzer bir şey daha hızlı Bundle.main.object(forInfoDictionaryKey: kCFBundleNameKey as String) olabilir .

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

benim durumumda bir NSDictionaryçağrı oluşturur appSettingsve gerekli tüm anahtarları eklerim. Bu durumda çözüm:

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

  }
}

Teşekkürler. objectForInfoDictionaryKeytam olarak aradığım şeydi.
LunaCodeGirl

2

Bunu kullanabilirsiniz, Sözlük için github'da basit bir uzantı oluşturuyorum 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
    }
}

Ve bunu yük için kullanabilirsiniz

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

İşte @connor'ın cevabına göre biraz daha kısa bir versiyon

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
}

Bence bunu yapmanın en kolay yolu.


2

DictionaryYerine basit bir başlatıcı yarattım NSDictionary(contentsOfFile: path). Sadece kaldırın 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
    }

}

Şöyle kullanabilirsiniz:

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 listesi ayrıştırıldı ve ayrıştırmak için kod, yukarıdaki https://stackoverflow.com/users/3647770/ashok-r cevabına dayanarak .

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

Adım 1 : Plist'i hızlı 3+ içinde ayrıştırmanın basit ve en hızlı yolu

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

2. Adım: Nasıl kullanılır:

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

0

İşte bulduğum çözüm:

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

Türünü beklenmeyen bir çıkarımla ilgili bir uyarıyı susturmak testiçin AnyObjectolarak ayarladım .

Ayrıca, bir sınıf yönteminde yapılmalıdır.

Bilinen türde belirli bir değere erişmek ve kaydetmek için:

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

0

Ben hızlı sözlükler kullanın ama benim gibi dosya yöneticisi sınıf NSDictionaries dönüştürmek:

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

Bu okuma ve yazma için en az rahatsız edici yol gibi görünüyor ama hadi benim kod geri kalanı mümkün olduğunca hızlı kalalım.


0

Plist , mülk listeleriyle çalışmak için yaptığım basit bir Swift numaralandırmadır.

// load an applications info.plist data

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

Daha fazla örnek:

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'in kendisi oldukça basit, doğrudan başvurmanız durumunda listesi.

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

.plist'den bir "2 boyutlu Dizi" okumak istiyorsanız, bunu şu şekilde deneyebilirsiniz:

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

0

SWIFT 5

Bazı anahtarlar için belirli bir değer almak istiyorsanız, Bundle'da infoDictionary özelliğini kullanan aşağıdaki uzantıyı kullanabiliriz .

Bundle.main.infoDictionaryform sözlüğündeki tüm info.plist değerlerini almak için kullanılabilir ve böylece Bundle'daki object(forInfoDictionaryKey: key)yöntemi kullanarak doğrudan sorgulama yapabiliriz

extension Bundle {
    static func infoPlistValue(forKey key: String) -> Any? {
        guard let value = Bundle.main.object(forInfoDictionaryKey: key) else {
           return nil
        }
        return value
    }
}

**How to Use:**

guard let apiURL = Bundle.infoPlistValue(forKey: "API_URL_KEY") as? String else { return }

-2

Plist dosyasına erişmek için basit yapı (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
}

Kullanımı:

print("someValue = \(Configuration.someValue)")
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.