Làm cách nào để tôi có được một từ như một từ điển trong Swift?


197

Tôi đang chơi xung quanh với ngôn ngữ lập trình Swift mới của Apple và gặp một số vấn đề ...

Hiện tại tôi đang cố đọc một tệp plist, trong Objective-C tôi sẽ làm như sau để có được nội dung dưới dạng NSDipedia:

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

Làm cách nào để tôi có được một từ như một từ điển trong Swift?

Tôi giả sử tôi có thể có được đường dẫn đến bản chính:

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

Khi điều này hoạt động (Nếu đúng?): Làm cách nào để tôi có được nội dung dưới dạng Từ điển?

Cũng là một câu hỏi tổng quát hơn:

Có thể sử dụng các lớp NS * mặc định không? Tôi nghĩ vậy ... hay tôi đang thiếu thứ gì đó? Theo như tôi biết thì các lớp NS * khung mặc định vẫn còn hiệu lực và có thể sử dụng được không?


Câu trả lời không còn giá trị, bạn có thể vui lòng chọn câu trả lời của Ashok không?
RodolfoAntonici

Câu trả lời:


51

Trong đọc nhanh 3.0 từ 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)")
        }
    }

Đọc thêm CÁCH SỬ DỤNG DANH SÁCH SỞ HỮU TÀI SẢN (.PLIST) TRONG SWift .


Askok. Mất nhiều giờ cố gắng để tìm một câu trả lời cho ngày hôm nay về điều này! CẢM ƠN BẠN!! Điều này làm việc hoàn hảo !!!
dùng3069232

281

Bạn vẫn có thể sử dụng NSDictionaries trong Swift:

Dành cho Swift 4

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

Dành cho Swift 3+

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

Và các phiên bản cũ hơn của 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
}

Các NSClass vẫn có sẵn và hoàn toàn tốt để sử dụng trong Swift. Tôi nghĩ rằng họ có thể sẽ muốn chuyển trọng tâm sang swift sớm, nhưng hiện tại các API swift không có tất cả các chức năng của NSClass cốt lõi.


hmm khi tôi thử sử dụng mã mà bạn cung cấp, tôi gặp lỗi: xxx không có thành viên tên là dict
KennyVB

nó hoạt động tốt trong sân chơi tho. không phải trong tài liệu nhanh chóng của tôi
KennyVB

Nó trông như thế nào nếu Array?
Arnlee Vizcayno

Hình như mainBundle()chỉ là maintrong Swift 3
BallpointBen

8
Câu trả lời này đã lỗi thời. Ngay cả trong Swift 3, bạn hoàn toàn không nên sử dụng NSArray/NSDictionaryđể đọc dữ liệu danh sách tài sản. PropertyListSerialization(và trong Swift 4 thay thế Codablegiao thức) là API thích hợp. Nó cung cấp xử lý lỗi hiện đại và dữ liệu có thể được chuyển đổi trực tiếp sang các loại bộ sưu tập Swift gốc.
vadian

141

Đây là những gì tôi làm nếu tôi muốn chuyển đổi .plist sang từ điển 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
  }
}

Đã chỉnh sửa cho Swift 2.0:

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

Đã chỉnh sửa cho 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
Tôi nghĩ rằng đây là câu trả lời "đúng" nhất của nhóm cho đến khi có một cách nhanh chóng riêng để làm điều này.
DudeOnRock

1
Câu trả lời này đã lỗi thời. Trong Swift 3, bạn hoàn toàn không nên sử dụng NSArray/NSDictionaryđể đọc dữ liệu danh sách tài sản. PropertyListSerialization(và trong Swift 4 thay thế Codablegiao thức) là API thích hợp. Nó cung cấp xử lý lỗi hiện đại và dữ liệu có thể được chuyển đổi trực tiếp sang các loại bộ sưu tập Swift gốc.
vadian

47

Swift 4.0

Bây giờ bạn có thể sử dụng giao thức Decodable để giải mã .plist thành một cấu trúc tùy chỉnh. Tôi sẽ đi qua một ví dụ cơ bản, đối với các cấu trúc .plist phức tạp hơn, tôi khuyên bạn nên đọc trên Decodable / Encodable (một tài nguyên tốt có ở đây: https://benscheirman.com/2017/06/swift-json/ ).

Đầu tiên hãy thiết lập cấu trúc của bạn thành định dạng của tệp .plist. Trong ví dụ này, tôi sẽ xem xét một .plist với Từ điển cấp gốc và 3 mục: 1 Chuỗi có khóa "name", 1 Int với khóa "age" và 1 Boolean với khóa "đơn". Đây là cấu trúc:

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

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

Đủ đơn giản. Bây giờ là phần mát mẻ. Sử dụng lớp PropertyListDecoder, chúng ta có thể dễ dàng phân tích tệp .plist thành một khởi tạo của cấu trúc này:

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

Không có nhiều mã để lo lắng, và tất cả trong Swift. Tốt hơn nữa là bây giờ chúng ta có một bản cấu trúc cấu hình mà chúng ta có thể dễ dàng sử dụng:

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

Điều này In giá trị cho các phím "tên", "tuổi" và "đơn" trong .plist.


1
Đó là câu trả lời tốt nhất cho Swift 4. Nhưng tại sao không Bundle.main.url(forResource: "Config", withExtension: "plist")và loại bỏ URL(fileURLWithPath? Và vì tệp được yêu cầu tồn tại (tại thời điểm thiết kế / biên dịch), tất cả các giá trị có thể bị hủy bỏ. Mã không được sập nếu mọi thứ được thiết kế đúng.
vadian

@vadian Chắc chắn bạn có thể sử dụng url(forResource: "Config", withExtension: "plist")Tôi chỉ khớp với những gì OP đã làm trong mã của họ làm điểm so sánh. Khi lực lượng tháo gỡ mọi thứ, tôi cố gắng hết sức thận trọng. Tôi nghĩ đó là một câu hỏi cơ bản cho Swift nói chung. Tôi muốn biết chính xác những gì mã của tôi sẽ làm trong mọi tình huống hơn là sự cố.
ekreloff

1) Vui lòng không áp dụng các thói quen xấu nếu có API phù hợp hơn. 2) Đó là một trong số ít trường hợp xảy ra sự cố bắt buộc phát hiện ra lỗi thiết kế. Bất kỳ tệp nào trong gói được yêu cầu phải có mặt tại thời gian biên dịch và không thể thay đổi khi chạy vì tất cả các tệp đều được ký mã. Một lần nữa: Mã không được sập nếu mọi thứ được thiết kế đúng .
vadian

Vâng, bạn biết quyền của bạn. Không nhận ra rằng đó là trường hợp với tài nguyên Bundle.
ekreloff

2
@NaveenGeorgeThoppan nếu bạn sử dụng ví dụ này làm từ điển thì đơn giản là như vậy decoder.decode([Config].self, from: data). (Lưu ý các dấu ngoặc quanh [Cấu hình])
ekreloff

22

Câu trả lời này sử dụng các đối tượng gốc Swift thay vì NSDipedia.

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

Có một phiên bản ngắn gọn cho điều này?
khắc nghiệt

18

Tôi đã làm việc với Swift 3.0 và muốn đóng góp câu trả lời cho cú pháp được cập nhật. Ngoài ra, và có thể quan trọng hơn, tôi đang sử dụng đối tượng PropertyListSerialization để thực hiện việc nâng vật nặng, nó linh hoạt hơn rất nhiều so với việc chỉ sử dụng NSDipedia vì nó cho phép một Array làm kiểu gốc của plist.

Dưới đây là một ảnh chụp màn hình của plist tôi đang sử dụng. Nó là một chút phức tạp, để hiển thị sức mạnh có sẵn, nhưng điều này sẽ làm việc cho bất kỳ sự kết hợp cho phép của các loại plist.

Mẫu hồ sơ Như bạn có thể thấy tôi đang sử dụng một từ điển Array of String: String để lưu trữ một danh sách các tên trang web và URL tương ứng của chúng.

Tôi đang sử dụng đối tượng PropertyListSerialization , như đã đề cập ở trên, để thực hiện công việc nặng nhọc cho tôi. Ngoài ra, Swift 3.0 đã trở nên "Swifty" hơn nên tất cả các tên đối tượng đã mất tiền tố "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)

Sau khi các đoạn mã trên chạy plistsẽ có kiểu Array<AnyObject>, nhưng chúng ta biết nó thực sự là loại gì để chúng ta có thể chuyển nó thành đúng loại:

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

Và bây giờ chúng ta có thể truy cập các thuộc tính khác nhau của Từ điển Chuỗi: Chuỗi theo cách tự nhiên. Hy vọng để chuyển đổi chúng thành các cấu trúc hoặc lớp được đánh máy mạnh mẽ;)

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

8

Tốt nhất là sử dụng từ điển và mảng bản địa vì chúng đã được tối ưu hóa để sử dụng với swift. Điều đó được nói rằng bạn có thể sử dụng các lớp NS ... nhanh chóng và tôi nghĩ rằng tình huống này đảm bảo điều đó. Đây là cách bạn sẽ thực hiện nó:

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

Cho đến nay (theo ý kiến ​​của tôi) đây là cách dễ nhất và hiệu quả nhất để truy cập vào một plist, nhưng trong tương lai tôi hy vọng rằng apple sẽ thêm nhiều chức năng hơn (như sử dụng plist) vào từ điển bản địa.


Theo như bạn biết, việc thêm đọc plist vào từ điển bản địa đã xảy ra chưa?
SpacyRicochet

8

Swift - Đọc / ghi plist và tập tin văn bản ....

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: Truy cập Info.Plist

Tôi có một Từ điển có tên CoachMarksDixi với giá trị boolean trong Info.Plist. Tôi muốn truy cập giá trị bool và làm cho nó đúng.

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

Viết cho Plist:

Từ một Plist tùy chỉnh: - (Tạo từ File-New-File-Resource-propertyList. Đã thêm ba chuỗi có tên: 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)
 }

Phương thức có thể được gọi là

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

Đây là những gì tôi đang tìm kiếm! Cảm ơn cậu!
Jayprakash Dubey

6

Chuyển đổi thành một tiện ích mở rộng tiện lợi thông qua câu trả lời của 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]
    }
}

sử dụng:

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

Tôi sẵn sàng đặt cược rằng nó cũng sẽ hoạt động để tạo một phần mở rộng tương tự cho Mảng


5

thực sự có thể làm điều đó trong 1 dòng

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

5

Bạn có thể đọc plist trong Ngôn ngữ SWIFT theo cách này:

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

Đọc giá trị từ điển đơn:

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

Nếu bạn muốn có được từ điển đa chiều đầy đủ trong plist:

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

Đây là số nguyên:

<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

Vì câu trả lời này chưa có ở đây, nên chỉ muốn chỉ ra rằng bạn cũng có thể sử dụng thuộc tính infoDipedia để lấy thông tin này làm từ điển , Bundle.main.infoDictionary.

Mặc dù một cái gì đó như Bundle.main.object(forInfoDictionaryKey: kCFBundleNameKey as String) thể nhanh hơn nếu bạn chỉ quan tâm đến một mục cụ thể trong phần thông tin.

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

trong trường hợp của tôi, tôi tạo một cuộc NSDictionarygọi appSettingsvà thêm tất cả các khóa cần thiết. Đối với trường hợp này, giải pháp là:

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

  }
}

Cảm ơn. objectForInfoDictionaryKeychính xác là những gì tôi đang tìm kiếm.
LunaCodeGirl

2

Bạn có thể sử dụng điều đó, tôi tạo một tiện ích mở rộng đơn giản cho Từ điển trong 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
    }
}

Và bạn có thể sử dụng nó để tải

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

Đây là phiên bản ngắn hơn một chút, dựa trên câu trả lời của @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
}

Cách dễ nhất để làm điều này theo ý kiến ​​của tôi.


2

Tôi đã tạo một trình Dictionarykhởi tạo đơn giản thay thế NSDictionary(contentsOfFile: path). Chỉ cần loại bỏ 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
    }

}

Bạn có thể sử dụng nó như vậy:

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

2

Danh sách Swift 4.0 iOS 11.2.6 được phân tích cú pháp và mã để phân tích cú pháp, dựa trên https://stackoverflow.com/users/3647770/ashok-r trả lời ở trên.

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

Bước 1 : Cách đơn giản và nhanh nhất để phân tích cú pháp trong 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
    }
}

Bước 2: Cách sử dụng:

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

0

Đây là giải pháp tôi tìm thấy:

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

Tôi thiết lập các loại testđể AnyObjectbịt miệng một lời cảnh báo về một kết luận bất ngờ có thể xảy ra.

Ngoài ra, nó phải được thực hiện trong một phương thức lớp.

Để truy cập và lưu một giá trị cụ thể của một loại đã biết:

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

0

Tôi sử dụng từ điển swift nhưng chuyển đổi chúng sang và từ NSDictionaries trong lớp trình quản lý tệp của mình như vậy:

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

Đây có vẻ là cách ít gặp rắc rối nhất để đọc và viết nhưng hãy để phần còn lại của mã của tôi ở lại càng nhanh càng tốt.


0

Plist là một enum Swift đơn giản mà tôi đã tạo ra để làm việc với danh sách tài sản.

// load an applications info.plist data

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

Ví dụ khác:

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

Bản thân Plist khá đơn giản, đây là danh sách của nó trong trường hợp bạn tham khảo trực tiếp.

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

nếu bạn muốn đọc "Mảng 2 chiều" từ .plist, bạn có thể thử nó như thế này:

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

Cấu trúc đơn giản để truy cập tệp 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
}

Sử dụng:

print("someValue = \(Configuration.someValue)")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.