Dictionary data structure returns nil in Swift - swift

I am trying to implement a dictionary data structure in swift that stores an Array of Strings. I have declared it like:
var journeyDetails = [Int: [String]]()
When I want to append an actual string to it, I do
if let journeys = fetchedData["journeys"] as? [[String: Any]]{
var nr_of_journey : Int = 0
for journey in journeys{
self.journeyDetails[nr_of_journey]?.append("The starting date and time of the journey are: "+String(describing: journey["startDateTime"]))
}
}
nr_of_journey = nr_of_journey + 1
etc etc. However, journeyDetails keeps returning nil. Should I do any other type of initialization? Why is the data not appended?

Initially there are no keys or values in journeyDetails so every use of self.journeyDetails[nr_of_journey] returns nil.
If you are using Swift 4, you can specify a default value to be used if there currently isn't a value for the given key.
Update the line:
self.journeyDetails[nr_of_journey]?.append("The starting date and time of the journey are: "+String(describing: journey["startDateTime"]))
to:
self.journeyDetails[nr_of_journey, default: []].append("The starting date and time of the journey are: "+String(describing: journey["startDateTime"]))
This provides a default empty array if there currently isn't a value for the given nr_of_journey key.

Related

How do put multiple values into a single key in Swift?

Is there a way to put multiple values in one key in Swift's dictionary, such as 'multimap' in Java?
var multiDic = [String:UserData]()
This is the dictionary I declared. it has this structure.
struct UserData{
var name: String
var id: String
var nickname: String
}
And when I put the value in one key in the dictionary, the value is updated without being stacked.
for key in 1...10 {
multiDic.updateValue(UserData(name:"name+\(key)", id:"id+\(key)", nickname:"nick+\(key)"), forKey: "A")
}
print(multiDic.count)
reults
1
How can I accumulate multiple values on a single key? I looked up a library called 'Buckets'
(https://github.com/mauriciosantos/Buckets-Swift#buckets), but there has been no update since swift 3.0.
Swift dictionary doesn't support this. One work around is to declare the dictionary to hold an array of values, like this:
var multiDic = [String:[UserData]]()
You would have to modify your code for adding values to work with the array instead of updating the value in place.
I haven't tried the "Buckets" project you mention, but for what it's worth, it probably still works either as-is or with minor changes.

Convert Realm list of Strings to Array of Strings in Swift

I'm just starting up with RealmSwift, and I'm trying to store an array of Strings in Realm. It doesn't work, so now I'm using List<String>() as an alternative. However, how do I convert these Realm Lists back to [String] again? And if I can't do that, are there any alternatives?
Thanks
However, how do I convert these Realm Lists back to [String] again
You can simply cast List to Array, because List has Sequence Support:
let list = List<String>()
let array = Array(list)
Bear in mind that by converting to an array you'll lose the 'dynamic' quality of a Realm collection (i.e. you'll receive a static array, whereas keeping the original List will provide automatic updating should the source change). But you can create an array by using an extension, e.g.:-
extension RealmCollection
{
func toArray<T>() ->[T]
{
return self.compactMap{$0 as? T}
}
}
Then use:-
let stringList = object.strings.toArray()
Where object is the realm object, and strings is your field.
Here are the details. how to assign an array in the realm list model.
jim.dogs.append(objectsIn: someDogs)

Realm Swift - Convert an array of results into an array of Ints

I want to convert the results from my Realm data into Int.
Here is an example of how I want to use this.
let results = realm.objects(Data.self)
print(results)
However the result is type Results<Data> and cannot be converted into a Int but the results is an Int.
Just to be clear I want an array of Int from my results
You can simply use Array(realm.objects(RealmType.self)), which will convert the Results<RealmType> instance into an Array<RealmType>.
However, there are other serious flaws with your code. First of all, neither of the last two lines will compile, since firstly realm.objects() accepts a generic input argument of type Object.Type and Data doesn't inherit from Object. You can't directly store Data objects in Realm, you can only store Data as a property of a Realm Object subclass.
Secondly, myArray[results] is simply wrong, since results is supposed to be of type Results<RealmType>, which is a collection, so using it to index an Array cannot work (especially whose Element type is different).
It appears that based on the number of results from the database, you want to select an object from the array.
You can get the number of items in an array with .count. Be certain that an object exists at the specified index in the array, or your application will crash!
let numberOfResults = results.count
if myArray.count > numberOfResults {
let object = myArray[numberOfResults]
print(object)
}

Swift 3: Only continue processing Dictionary value if it's of type Array

I am receiving a data structure over the wire that's of type [String: AnyObject]. The reason for AnyObject is simply because the value can be of type Array or Dictionary. My condition is straight forward:
if let data = list["foo"], data.count > 0 {
// do stuff
}
My problem is, I only want that condition to pass if data is an Array. The condition I have fails because count property seems to work on a Dictionary as well (It probably counts the number of keys in the dictionary).
What's the best way to handle this?
You can cast data as an Array in your if statement:
if let data = list["foo"] as? [Any], data.count > 0 {
// do stuff
}
This will make sure that data is an Array before doing any operations on it.

Dictionary saved to NSUserDefaults always returns nil

I'm trying to save a dictionary to NSUserDefaults using the setObject() function but when I use the objectForKey() function to retrieve the dictionary it returns nil. Why is this happening?
var data = NSUserDefaults.standardUserDefaults();
var scoreboard = [Int : String]()
let scores = "scoresKey"
scoreboard[3] = "spencer"
scoreboard[6] = "brooke"
scoreboard[11] = "jason"
data.setObject(scoreboard, forKey: scores)
data.objectForKey(scores) // Returns nil
The first problem was that it's not possible to use NSUserDefaults in a Playground.
See: https://stackoverflow.com/a/31210205/3498950
A second problem is found when the code above runs in a normal iOS project. It throws an NSInvalidArgumentException since the dictionary was a non-property list object because the keys needed to be of type String.
Although NSDictionary and CFDictionary objects allow their keys to be
objects of any type, if the keys are not string objects, the
collections are not property-list objects.
See: "What is a Property List?" in the Apple Docs