Remove NSArray duplicate Items - ios

How I remove Plist repeated values in Swift?
if let bundlePath = Bundle.main.path(forResource: "Places", ofType: "plist") {
if let dicionario = NSDictionary(contentsOfFile: bundlePath) {
places = dicionario["places"] as? NSArray
//places = Array(Set(places))
tableView.reloadData()
}
}
I've tried to use places = Array(Set(places)) but I have an error
Can I convert NSArray to Array?

Related

Swift: Reading plist - How to filter by key and read and append value only

Swift 3
I'm trying to read a plist file to update my array for collection view.
My menu.plist has 6 items that I want to read and append to my array that uses .count to update the collection view.
Problem is I'm having trouble sorting the dictionary. I want to append the strings in value to my array but sort the transfer by the key which has the text "Item 0", "Item 1", etc. Because the array comes unorganized which makes it harder to use the switch statements on didSelectItemAt.
In the code I'm not using key only appending value to mainGroup array but its unorganized and I need to filter it by the plist key
Code in ViewDidLoad
var mainGroup = [String]()
var myDict: NSDictionary?
if let path = Bundle.main.path(forResource: "menu", ofType: "plist") {
myDict = NSDictionary(contentsOfFile: path)
}
if let dict = myDict {
print(dict)
for (_, value) in dict {
mainGroup.append("\(value)")
}
print(mainGroup)
}
Plist
You need sort your dict.keys array and the access to value by those sorted keys
Full code
var mainGroup = [String]()
var myDict: [String:String]?
if let path = Bundle.main.path(forResource: "menu", ofType: "plist") {
myDict = NSDictionary(contentsOfFile: path) as? [String:String]
}
if let dict = myDict {
print(dict)
for key in dict.keys.sorted() {
mainGroup.append(dict[key]!)
}
print(mainGroup)
}
update
Using array as #rmaddy says
var mainGroup = [String]()
var myArray: [String]?
if let path = Bundle.main.path(forResource: "menu", ofType: "plist") {
myArray = NSArray(contentsOfFile: path) as? [String]
}
print(myArray)

Swift 3 - How to access a property list

This is from a property list I created:
I want to load just the country names into an array. Here's the code I have so far...
if let path = Bundle.main.path(forResource: "flagData", ofType: "plist") {
dict = NSMutableDictionary(contentsOfFile: path)
let currentGroup = (dict!["caribbean"] as AnyObject).allKeys as? [String]
}
But that doesn't work - when I run it, currentGroup = nil
I also tried:
let currentGroup = dict?.allKeys(for: "caribbean")
But that gives me an empty array.
Any ideas will be appreciated... Thanks!
if let path = Bundle.main.path(forResource: "flagData", ofType: "plist"),
let configurations = NSDictionary(contentsOfFile: path) {
variables = configurations[currentConfiguration] as! NSDictionary
}
Try the above code and make relevant changes i think error in your code is while you cast its failing.

"fatal error: unexpectedly found nil while unwrapping an Optional value" received when using NSFileManager to retrieve multiple values

I receive the following error when I attempt to retrieve multiple values using NSFileManager: fatal error: unexpectedly found nil while unwrapping an Optional value
Here is my code:
class func loadGameData() -> (HighScore: Int, HasCompletedTutorial: Bool) {
// getting path to GameData.plist
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let documentsDirectory = paths[0] as! String
let path = documentsDirectory.stringByAppendingPathComponent("GameData.plist")
let fileManager = NSFileManager.defaultManager()
//check if file exists
if(!fileManager.fileExistsAtPath(path)) {
// If it doesn't, copy it from the default file in the Bundle
if let bundlePath = NSBundle.mainBundle().pathForResource("GameData", ofType: "plist") {
let resultDictionary = NSMutableDictionary(contentsOfFile: bundlePath)
fileManager.copyItemAtPath(bundlePath, toPath: path, error: nil)
}
}
let resultDictionary = NSMutableDictionary(contentsOfFile: path)
var myDict = NSDictionary(contentsOfFile: path)
if let dict = myDict {
//loading values - THIS IS WHERE THE ERROR OCCURS
let HighScore: AnyObject = dict.objectForKey("HighScore")!
let CompletedTutorial: AnyObject = dict.objectForKey("HasCompletedTutorial")!
return (Int(HighScore as! NSNumber), Bool(CompletedTutorial as! NSNumber))
}
return (0, false)
}
I have tested both of the lines by themselves, and they work perfectly. But they don't seem to work together
Here is the code used to call the function
let val = GameData.loadGameData()
println(val.HighScore)
println(val.HasCompletedTutorial)
I have tested multiple variants of this function call and it has not made a difference
Thank You
Why don't you unwrap them? Try something like this
if let dict = myDict {
if let
highScore = dict.objectForKey("HighScore"),
completedTutorial = dict.objectForKey("HasCompletedTutorial")
{
return (Int(highScore as! NSNumber), Bool(completedTutorial as! NSNumber))
}
}

How to add new array data to NSDictionary in plist file using Swift

I have a plist file ("myAwayList.plist") to store navigation data. I have nested a Dictionary of String variables in an Array in the main Dictionary as follows..
<dict>
<key>Locations</key>
<array>
<dict>
<key>Name</key>
<string>Sydney City Centre</string>
<key>Address</key>
<string>Centrepoint Tower</string>
<key>Lat</key>
<string>-33.870451</string>
<key>Lon</key>
<string>151.208771</string>
</dict> ...
I can successfully load and use the array data inside with the following...
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let documentsDirectory = paths.objectAtIndex(0)as NSString
let path = documentsDirectory.stringByAppendingPathComponent("myAwayList.plist")
let fileManager = NSFileManager.defaultManager()
// Check if file exists
if(!fileManager.fileExistsAtPath(path))
{
// If it doesn't, copy it from the default file in the Resources folder
let bundle = NSBundle.mainBundle().pathForResource("myAwayList", ofType: "plist")
fileManager.copyItemAtPath(bundle!, toPath: path, error:nil)
println("File did not exist! Default copied...")
}
let dict = NSDictionary(contentsOfFile: path)!
let mySavedLocations: AnyObject = dict.objectForKey("Locations")!
println("plist all: \(mySavedLocations)")
if let nsArray:NSArray = mySavedLocations as? NSArray{
for var loadCount = 0; loadCount < mySavedLocations.count; ++loadCount {
var locationDict:AnyObject = nsArray[loadCount] // loading array data at index
let arrayName = locationDict["Name"] as AnyObject? as String
let arrayAddress = locationDict["Address"] as AnyObject? as String
let arrayLat = locationDict["Lat"] as AnyObject? as String
let arrayLon = locationDict["Lon"] as AnyObject? as String
awaydatalist.append(AwayData(name:arrayName, address:arrayAddress, lat:arrayLat, lon:arrayLon)) // This is a list array used to display the loaded data on a ViewController
}
}
I now want to append the array inside with another row of data, and write back to the plist file, but I cannot find a way to do it. Please advise?
Chris
Here is the code to add new Dictionary inside the array stored in plist file
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let documentsDirectory = paths.objectAtIndex(0)as NSString
let path = documentsDirectory.stringByAppendingPathComponent("myAwayList.plist")
let fileManager = NSFileManager.defaultManager()
// Check if file exists
if(!fileManager.fileExistsAtPath(path))
{
// If it doesn't, copy it from the default file in the Resources folder
let bundle = NSBundle.mainBundle().pathForResource("myAwayList", ofType: "plist")
fileManager.copyItemAtPath(bundle!, toPath: path, error:nil)
println("File did not exist! Default copied...")
}
let dict = NSMutableDictionary(contentsOfFile: path)!
let mySavedLocations: AnyObject = dict.objectForKey("Locations")!
println("plist all: \(mySavedLocations)")
if let nsArray:NSArray = mySavedLocations as? NSArray
{
for var loadCount = 0; loadCount < mySavedLocations.count; ++loadCount
{
var locationDict:AnyObject = nsArray[loadCount] // loading array data at index
let arrayName = locationDict["Name"] as AnyObject? as String
let arrayAddress = locationDict["Address"] as AnyObject? as String
let arrayLat = locationDict["Lat"] as AnyObject? as String
let arrayLon = locationDict["Lon"] as AnyObject? as String
// awaydatalist.append(AwayData(name:arrayName, address:arrayAddress, lat:arrayLat, lon:arrayLon)) // This is a list array used to display the loaded data on a ViewController
}
}
//Convert AnyObject to NSMutableArray
var twDataArray = (mySavedLocations as NSMutableArray) as NSMutableArray
//Create a new Dictionary
let airports: [String: String] = ["Name": "Toronto Pearson", "Address": "Dublin","Lat":"23.23","Lon":"78.89"]
//add dictionary to array
twDataArray.addObject(airports)
//set the new array for location key
dict.setObject(mySavedLocations, forKey: "Locations")
//update the plist
dict.writeToFile(path, atomically: true)
This code add a new dictionary inside the location array.

How can I read data from a PLIST in Swift?

i'm facing a problem with reading data from a plist file using swift
my code:
let Chapterpath = NSBundle.mainBundle().pathForResource("chapterMapping", ofType: "plist")
let dict2 = NSDictionary(contentsOfFile: Chapterpath!)
let chaptername = dict2?.objectForKey("chapterName")
let chapterNumber = dict2?.objectForKey("pageNumber")
next i'm trying to add plist data to an array, should i simply use
var myArray = [chapterName]
my question: is the code above correct?
or im i missing something
and when i tried to print plist data using println((chapterName))
i got an error
thank you
First, your Root object in the plist is an NSArray not a NSDictionary.
Second, if you want to use KVC on Foundation Collections (I don't believe this works with Swift's Array) you need to call valueForKeyPath.
let chapterPath = NSBundle.mainBundle().pathForResource("chapterMapping", ofType: "plist")
if let arrayOfItems: [AnyObject] = NSArray(contentsOfFile: chapterPath!) {
let chapterNames: [String] = arrayOfItems.valueForKeyPath("chapterName") as NSArray as [String]
let pageNumbers: [Int] = arrayOfItems.valueForKeyPath("pageNumber") as NSArray as [Int]
}
Third, the swift-y way of doing this would be with the map function, but arrayOfItems would need to be a strongly-defined type and it might be more work than it's worth. Example:
let array: [ChapterMetaData] = // define it here
let chapterImages = array.map { $0.chapterImage }
As you say you have an array with multiple element. objectForKey does not search the hall tree levels and gets you the first one with the name. you have multiple values a loop must be envolved. Try the following:
var Chapterpath:NSString = NSBundle.mainBundle().pathForResource("chapterMapping", ofType: "plist");
var chapters:NSArray = NSArray(contentsOfFile: Chapterpath);
for chapter in chapters {
let chaptername = chapter["chapterName"]
let chapterNumber = chapter["pageNumber"]
println(chaptername);
}
Use following code to read Plist data to NSArray:
let path = NSBundle.mainBundle().pathForResource(plistName, ofType: "plist")
var list = NSArray(contentsOfFile: path!) as [[String:String]]
Simplest way to parse the AppConfig.plist file in project:
var dictionaryObj: NSDictionary?
if let filePath = NSBundle.mainBundle().pathForResource("AppConfig", ofType: "plist")
{
dictionaryObj = NSDictionary(contentsOfFile: filePath)
}
if let dict = dictionaryObj
{
//parse it as NSDictionary
}
else
{
//dictionaryObj is nil or doesn't contain anything.
}
You can use NSArray if Plist Root is Array:
let path = NSBundle.mainBundle().pathForResource("OrderHelper", ofType: "plist")
let myArray = NSArray(contentsOfFile: path!)
You can use NSDictionary if Plist Root is Dictionary:
let path = NSBundle.mainBundle().pathForResource("OrderHelper", ofType: "plist") {
let myDict = NSDictionary(contentsOfFile: path!)

Resources