13

I have created a mini translation from English words to Spanish words. I would like to use the englishArray.plist instead of my englishArray = ["the cat"] How can I create this?

enter image description here

I have also used a localizable.strings to retrieve the value "the cat" for "el gato" but I would like to retrieve this from englishArray.plist

I started off with this but not sure if I'm on the right path

let path = NSBundle.mainBundle().pathForResource("englishArray", ofType: "plist") 
let plistEnglishArray = NSArray(contentsOfFile: path!)

Here is the rest of my code:

var englishArray: [String] = ["rainbow", "boots", "heart", "leaf", "umbrella", "tired", "angry", "cry", "the cat" ]


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    self.translateTextField.delegate = self
    picker.delegate = self
    picker.dataSource = self
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

@IBAction func translateButtonTapped(sender: UIButton) {

    let emptyString = self.translateTextField.text

    if (emptyString!.isEmpty) {

        print("please enter a word")

    }

    for transIndex in englishArray.indices {
        if englishArray[transIndex] == emptyString!.lowercaseString {

            //englishArray

            //translateLabel.text = "\(spanishArray[transIndex])"
            translateLabel.text = NSLocalizedString(emptyString!.lowercaseString, comment:"")


            print(emptyString)
            return

        }
    }
}
Miguel
  • 213
  • 1
  • 3
  • 12
  • Your root object it is a dictionary. You have two options: Import the dictionary or fix your plist file – Leo Dabus Apr 23 '16 at 14:56

5 Answers5

17

Swift 4

The absolute simplest way to do this is

    let url = Bundle.main.url(forResource: "Sounds", withExtension: "plist")!
    let soundsData = try! Data(contentsOf: url)
    let myPlist = try! PropertyListSerialization.propertyList(from: soundsData, options: [], format: nil)

The object myPlist is an Array or Dictionary, whichever you used as the base of your plist.

Paul Linsay
  • 449
  • 4
  • 6
  • assuming you have this code inside viewDidLoad(), how do you then share the myPlist variable to other files? – alamodey Jul 22 '19 at 12:00
9

Change your root object to Array, then

var myEnglishArray: [String] = []
if let URL = NSBundle.mainBundle().URLForResource("englishArray", withExtension: "plist") {
      if let englishFromPlist = NSArray(contentsOfURL: URL) as? [String] {
        myEnglishArray = englishFromPlist
      }
    }
Twitter khuong291
  • 11,328
  • 15
  • 80
  • 116
  • why don't you just cast your NSArray using conditional cast `if let englishArray = NSArray(contentsOfURL: url) as? [String] {` – Leo Dabus Apr 23 '16 at 15:06
  • 1
    you don't need an extra array and/or append `if let url = NSBundle.mainBundle().URLForResource("englishArray", withExtension: "plist"), englishArray = NSArray(contentsOfURL: url) as? [String] { for word in englishArray { print(word) } }` – Leo Dabus Apr 23 '16 at 15:09
  • is this code placed in viewDidLoad() right? @khuong291 – Miguel Apr 23 '16 at 15:26
  • If you need to convert your array to data you can use keyed archiver – Leo Dabus Apr 23 '16 at 15:31
  • 1
    I am not really sure why you are converting a `[String]` array into another `[String]`. Why not just `myEnglishArray = englishFromPlist` instead `for-in`? – Sulthan Apr 23 '16 at 15:35
7

Swift 4

You can use Codable which is pure swift type.

Firstly load Plist file from bundle then use PropertyListDecoder

Complete code -

    func setData() {
        // location of plist file
        if let settingsURL = Bundle.main.path(forResource: "JsonPlist", ofType: "plist") {

            do {
                var settings: MySettings?
                let data = try Data(contentsOf: URL(fileURLWithPath: settingsURL))
                    let decoder = PropertyListDecoder()
                settings = try decoder.decode(MySettings.self, from: data)
                print("array  is \(settings?.englishArray ?? [""])")//prints array  is ["Good morning", "Good afternoon"]


            } catch {
                print(error)
            }
        }
    }
}
struct MySettings: Codable {

    var englishArray: [String]?

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        englishArray = try values.decodeIfPresent([String].self, forKey: .englishArray)

    }
}
Jack
  • 13,571
  • 6
  • 76
  • 98
0

This will read a resource in your bundle with the name "englishArray.plist" and store it in the immutable variable english. It will be an Optional that you should test before using.

It uses a closure to read the file and return the array, this lets you use a immutable value rather than a mutable variable that can be changed. It's a good idea to use immutables wherever you can - they promote stability.

import Foundation

let english:[String]? = {
  guard let URL = NSBundle
    .mainBundle()
    .URLForResource("englishArray", withExtension: "plist") else {
      return nil
  }
  return NSArray(contentsOfURL: URL) as? [String]
}()
0

Here is the solution for swift 3. For this solution you do not need to change types in your plist structure (keep Dictionary, Array, as is). Also note that since your array's name in plist is also englishArray so the (value for key) argument in the second if statement is also englishArray.

var myEnglishArray: [String] = []
   if let URL = Bundle.main.url(forResource: "englishArray", withExtension: "plist") {
      guard let englishFromPlist = NSDictionary(contentsOf: URL) else { return [] }
      if let englishArray = englishFromPlist.value(forKey: "englishArray") as? [String] {
         for myEnglish in englishArray {
            myEnglishArray.append(myEnglish)
         }
      }
   }
Ohmy
  • 2,201
  • 21
  • 24