WokerHead
WokerHead

Reputation: 967

Swift: How to read multiple array within array in plist?

This is my plist

Collections View

pic1

With Swift 3, I'm reading the plist to fill my arrays with this code perfectly but I do not know how to access the plist when it has arrays inside the root array

The code I use to read when the root is an array

var mainGroup = [String]()

var myArray: [String]?
if let path = Bundle.main.path(forResource: "items", ofType: "plist") {
    myArray = NSArray(contentsOfFile: path) as? [String]
}

mainGroup = myArray!

But in this plist, theres more arrays to read than just the root. I would like to read how many arrays the root has so in my collection view I use it in numberOfItemsInSection, cellForItemAt and didSelectItemAt. And I would like to also read items inside the arrays to display it in detail view of the collections for when an item is selected.

Conclusion: I want to read how many arrays are in root array to use it in .count and how to access the items in the arrays to display it in another view controller as detail. To access an array it would be array[2] but how would that work if I wanted to display the string "Jeans" and "4" , etc. Thank you

Upvotes: 3

Views: 1285

Answers (4)

XX.Alex
XX.Alex

Reputation: 7

I guess that you make a mistake in data structure.Maybe you can try the code below...

var mainGroup = [[Any]]()

var myArray: [[Any]]?
if let path = Bundle.main.path(forResource: "items", ofType: "plist") {
    myArray = NSArray(contentsOfFile: path)
}

if let myArr = myArray {
   mainGroup = myArr
}

Upvotes: -1

vadian
vadian

Reputation: 285079

The recommended way in Swift to read a property list file is PropertyListSerialization. It avoids the usage of Foundation NSArray.

The code prints the section numbers and all items in the inner array.

If the property list is is supposed to populate a table view I recommend to declare the inner array as dictionary.

let url = Bundle.main.url(forResource:"items", withExtension: "plist")!
do {
    let data = try Data(contentsOf:url)
    let sections = try PropertyListSerialization.propertyList(from: data, format: nil) as! [[Any]]

    for (index, section) in sections.enumerated() {
        print("section ", index)
        for item in section {
            print(item)
        }
    }
} catch {
    print("This error must never occur", error)
}

Upvotes: 7

Jack
Jack

Reputation: 14329

I have added comment respectively with rootArray & subArray enter image description here

   override func viewDidLoad() {
        super.viewDidLoad()
        readPlist()
    }
    func readPlist(){
        let path = Bundle.main.path(forResource: "SampleData", ofType: "plist")
        let rootArray = NSArray(contentsOfFile: path!)!
        print(rootArray.count)//Gives count for total objects. You can use in number of rows

        for data in rootArray {
            let subArray = data as? NSArray ?? []
            print(subArray.count)//Gives you subarray count
            for value in subArray {
                print("objects are \(value)")//Gives you contains of subarray
            }
        }

    }
}

Upvotes: 2

Puneet Sharma
Puneet Sharma

Reputation: 9484

struct ParsePlist {
    let plistName:String

    init(name:String) {
        plistName = name
    }

    func sectionArrayFromPlist() -> [[Any]]? {

        guard let plistPath = Bundle.main.path(forResource: plistName, ofType: "plist") else {
            return nil
        }

        guard let rootArray = NSArray(contentsOfFile: plistPath) as? [Any] else {
            return nil
        }

        var sectionArray:[[Any]]?
        sectionArray = rootArray.flatMap({ $0 as? [Any]})
        return sectionArray
    }
}

use:

let parsePlist = ParsePlist(name: <yourplistname>)
if let sectionArray = parsePlist.sectionArrayFromPlist() {
   // use sectionArray
}

Upvotes: 0

Related Questions