Accessing swift array inside a swift dictionary - ios

I have a function is that takes a dictionary, and I need to parse the information inside.
I can get an NSArray out of the dictionary, but shouldn't I be able to access a native swift array?
class func parseResults(resultsDict:Dictionary<String, AnyObject>) -> Array<Track>? {
var results : NSArray = resultsDict["results"] as NSArray // This works
//var results : Array = resultsDict["results"] as Array<AnyObject> // This doesnt work
...
}

A native Swift array is implemented as a struct so it isn't an AnyObject. If you have your dictionary contain <String, Any> instead, it should work since Array does conform to Any.

Array is struct, which is not object so it you can't convert it from AnyObject
On the other hand, NSArray is class, so you can convert it from AnyObject.

You could wrap the array in a class and that will solve your problem
class WrappedArray<T> {
var array = Array<T>()
}
var dict = Dictionary<Int, WrappedArray<Int>>()
dict[0] = WrappedArray<Int>()
dict[0].array.append(0)
dict[0].array.append(1)
...
You could also implement array methods in the wrapper class and forward them to the array
class WrappedArray<T> {
var array = Array<T>()
func append(_ newElement:T) {
self.array.append(newObject)
}
}
Then you can use it like a regular array.
dict[0].append(0)
instead of
dict[0].array.append(0)

Related

2 arrays into one dictionary while maintaining the indexes

I have two separate arrays that I want to import into a dictionary. Order is extremely important because both arrays must match in index
struct MyVariables {
static var users:NSArray!
static var img:NSArray!
}
var data = SearchVC.getData()
MyVariables.users = data.users; //array 1 (key)
MyVariables.img = data.img; //array 2
// Goal is to insert these arrays into a dictionary while maintaing the matching indexes on both arrays
// Dictonary (MyVariables.img, key: MyVariables.users)
A Dictionary does not have a particular order. However, if both arrays have the same length, it is quite easy to iterate over them together:
var dictionary = [NSString: AnyObject]()
for var index = 0; index < data.users.count; index++ {
let img = data.img as! NSString
dictionary[img] = data.users[index]
}
Or, as #robertvojta suggested, use the zip() method:
var dictionary = [NSString: AnyObject]()
for (user, image) in zip(data.users, data.img) {
let img = image as! NSString
dictionary[img] = user
}
The key in a dictionary in swift must be hashable. i.e., not AnyObject.
Assuming you can replace some of your untyped Swift arrays, or cast them like so:
struct MyVariables {
var users:Array<AnyObject>
var img:Array<String>
}
then you can iterate through 1 array using a preferred Swift method and access the second using indexing:
var dictionary = Dictionary<String, AnyObject>()
for (index, element) in enumerate(MyVariables.img) {
dictionary[element] = MyVariables.users[index]
}
Use for loop for travels the array in that as per index access keys and values respective array and add it in dictionary. Its so simple so you can achive your goal using it.
I hope it will help you!

Passing String array to a function

I am trying to pass an array to a function:
var array:[String] = []
// fill the array
array.append(uniqueId as String)
// pass the array to a function:
GamePrefrences.setLevelsArray(array)
My function is declares like this:
func setLevelsArray(arr:[String])
{
GamePrefrences.levels_array = arr
}
But on the line i try to call the function it gives with an error:
cannot invoke ... with argument list of type [(String)]
What is the problem? if its possible to provide brief explanation
First of all, your function is not a class level function and you are calling the method directly using class name.
Try like this.
var array:[String] = []
// fill the array
array.append(uniqueId as! String)
// pass the array to a function:
GamePrefrences.setLevelsArray(array)
Function declaration.
class func setLevelsArray(arr:[String])
{
GamePrefrences.levels_array = arr
}
or,
var array:[String] = []
// fill the array
array.append(uniqueId as String)
// pass the array to a function:
let instance = GamePrefrences()//Depends on you, how you defined the initialiser.
instance.setLevelsArray(array)
Your function body.
func setLevelsArray(arr:[String])
{
instance.levels_array = arr
}
please try something like this
func setLevelsArray(arr:[String])
{
let tempArr = arr
GamePrefrences.levels_array = tempArr
}
in Swift Arrays and Dictionary are passed by value not by reference, therefore if you are not changing the values or assigning to any other variable then Swift compiler does not get the copy, instead the variable still lives in the heap. so before assigning i believe it is necessary to copy this into another variable.
You have invalid declaration of an empty array. Here's how to declare empty array:
var array = [String]()

Get object type from empty Swift Array

Is there a way to get instance of Array element from the empty array? (I need dynamic properties because I use some KVC methods on NSObject)
import Foundation
class BaseClass: NSObject {
func myFunction() {
doWork()
}
}
class Car: BaseClass {
dynamic var id: Int = 0
}
class Bus: BaseClass {
dynamic var seats: Int = 0
}
var cars = Array<Car>()
What I need is a vay to get instance of empty Car object from this empty array, for example like this:
var carFromArray = cars.instanceObject() // will return empty Car object
I know that I can use:
var object = Array<Car>.Element()
but this doesn't work for me since I get array from function parameter and I don't know it's element class.
I have tried to write my own type that will do this, and it works, but then I cannot mark it as dynamic since it cannot be represented in Objective C. I tried to write extension of Array
extension Array {
func instanceObject<T: BaseClass>() -> T? {
return T()
}
}
but when I use it, it sometimes throws error fatal error: NSArray element failed to match the Swift Array Element type
Swift 3: Get an empty array's element type:
let cars = [Car]() // []
let arrayType = type(of: cars) // Array<Car>.Type
let carType = arrayType.Element.self // Car.Type
String(describing: carType) // "Car"
This seems to work as of Swift 2.0:
let nsobjectype = cars.dynamicType.Element()
let newCar = nsobjectype.dynamicType.init()
Not sure if it will work in earlier versions.
Something like this?
let cars = Array<Car>()
let car = cars.dynamicType.Element()

How to use Swift specific containers in containers?

I have a Dictionary that holds another Dictionary that holds an Array which holds another Array of a custom class. I'm having a lot of trouble working with these can someone who this comes easy to tell me the ways I can define, initialize, and access and assign to either part specifically.
Dic = [String: [String: [[MyClass]]]]
Sorry if it's confusing.
This code shows you how to do what you asked, but the data structure you requested is quiet cumbersome to use. I'll recommend to think again about what you want to accomplish and review this data structure.
class MyClass {
var name : String
init(name: String) {
self.name = name
}
}
// Create your dictionary
var dic : [String: [String: [[MyClass]]]] = [:]
// Create a list of MyClass object
var list = [MyClass(name: "first"), MyClass(name: "second"), MyClass(name: "third")]
// Create a dictionary with string key and array of array of type MyList
var myClassDic = ["test": [list]]
// update or add new value via the updateValue method
dic.updateValue(myClassDic, forKey: "index1")
// update or add new value via the subscript
dic["index2"] = ["test2": [[MyClass(name: "forth"), MyClass(name: "fith")]]]
// Iterate over your outer dictionairy
for key in dic.keys {
// retrieve an entry from your outer dictionary
var tempDic = dic[key]
// Iterate over your inner dictionary
for sKey in tempDic!.keys {
// retrieve an array of array of MyList Object
var containerList = tempDic![sKey]
// iterate over the outer array
for listVal in containerList! {
//Iterate over the inner array
for sListVal in listVal {
print("\(sListVal.name) ")
}
println()
}
}
}

Error trying to access members of Array of AnyObject within a Dictionary - Is there a way around unwrapping?

I have a dictionary set up as:
var jDict = Dictionary<String, AnyObject[]>()
Where the arrays are either a collection of custom buttons (JunkButton) or Labels (JunkLabels).
I am having an issue when trying to access the members of the arrays contained in the Dictionary as follows:
let thisArray = jDict[key]
var aButton = thisArray[0] //Gives error: 'AnyObject[]? does not have a member named 'subscript'
I can get around this by downcasting the whole array as follows:
if let aArray = thisArray as? JunkButton[]{
var aButton = aArray[0]
}
This seems very cumbersome especially if I am sure I know what type the array is made up of beforehand. Is there a way to cast thisArray when it is created that would allow me to extract its elements without unwrapping them each time?
Dictionary always give you Optional value.
Your code is like this
let thisArray : Optional<AnyObject[]> = jDict[key]
You need to unwrap it to get non-optional value
let thisArray = jDict[key]! // thisArray is AnyObject[]
You really shouldn't use a dictionary for this. Swift makes it very easy to use custom little structs or classes instead of dictionaries:
struct JunkItems {
var buttons: [JunkButton] = []
var labels: [JunkLabel] = []
}
Then you can access those items like this without downcasting:
for button in junkItems.buttons {
// ...
}
Or:
if let button = junkItems.buttons[0] {
// ...
}
Btw, the array notation [JunkButton] is new in beta 3.

Resources