How to assign a Dictionary to AnyObject in swift - arrays

I have been playing around with Swift. I have had multiple errors with types, especially working with Swift and my old Objective-C classes. The problem with this method is: I am expecting an array made of NSDictionarys in Objective-C.
var curArr:[Dictionary<String, AnyObject>] = self.getItemsForCurrentStack()
var arrToReturn:[(Dictionary<String, AnyObject?>)] = []
for obj in curArr{
arrToReturn.append(["image": UIImage(named: obj["imageName"] as! String), "color": UIColor(red:obj["colorDic"]!["red"] as! CGFloat, green:obj["colorDic"]!["green"] as! CGFloat, blue:obj["colorDic"]!["blue"] as! CGFloat, alpha:1.0), "percentage": obj["percantage"]])
}
return arrToReturn
This returns Dictionaries (which are NSDictionaries) in Swift. But the last line throws me an error:
Dictionary' is not identical to 'AnyObject'
I've tried using as! [AnyObject]
But that throws another error:
'AnyObject' is not a subtype of 'Dictionary'
I don't get the second error, since this doesn't have to be a subtype, but the other way around. Any ideas on how to solve this? I didn't find an answer for several hours of googleing and researching.

Dictionary is a struct in Swift, whereas AnyObject is
/// The protocol to which all classes implicitly conform.
Depending what you're trying to do, you may want to use Any in your code, or cast your dictionary to NSDictionary using as NSDictionary.
Edit after your clarification:
If you split up the append call from the dictionary itself, you see a better error message:
So, the issue is that your dictionary contains some Optional values, but Optional is a struct and not convertible to Obj-C. You can fix by casting to UIImage! and AnyObject! (ImplicitlyUnwrappedOptional), or by using as!.

Your code works fine in playground, without compile or runtime errors. Here is what I added to populate curArr:
var curArr:[Dictionary<String, AnyObject>] = [
[
"imageName" : "photo.jpg",
"colorDic" : ["red" : 1.0, "green" : 0.0, "blue" : 0.0],
"percentage" : 0.5
]
]
With all this forced unwrapping I think you just have to make sure that what self.getItemsForCurrentStack() returns is indeed what you expect.
Result in playground:
[
"percentage": {Some 5.0e+-1},
"image": nil,
"color": {Some r 1,0 g 0,0 b 0,0 a 1,0}
]
My recommendation would be to refactor into objects - that would make your code so much more readable!

In Swift 3
code:
var curArr:[Dictionary<String, Any>] = [
[
"imageName" : "photo.jpg",
"colorDic" :[
"red" : 1.0,
"green" : 0.0,
"blue" : 0.0
],
"percentage" : 0.5
]
]

Related

Cannot assign value of type '[String]' to type 'String?' error Swift

So I know many people have asked a similar question like this before but I'm still not able to get this working after following those solutions. I'm trying to generate a random color car from two arrays and store that in a dictionary. My code is below:
var colorTypeDictionary = [String:String]()
var colorArray = ["Red", "Black", "Silver", "Yellow", "Orange", "Blue", "Purple", "Pink", "White", "Gray", "Green"]
var carTypeArray = ["Ferarri", "Lamborghini", "Porsche", "Aston Martin", "Maserati"]
colorTypeDictionary[colorArray.randomElement()!] = [carTypeArray.randomElement()!]
print(colorTypeDictionary)
I keep getting the error around
[carTypeArray.randomElement()!]. It says: Cannot assign value of type '[String]' to type 'String?'.
I've tried casting that line as a String but can't get it to work. Does anyone know why this is happening?
Thanks!
You just need to remove the square brackets:
colorTypeDictionary[colorArray.randomElement()!] = carTypeArray.randomElement()!
[carTypeArray.randomElement()!] is of type [String] that you can't assign to dictionary value of type String , so Replace
colorTypeDictionary[colorArray.randomElement()!] = [carTypeArray.randomElement()!]
with
colorTypeDictionary[colorArray.randomElement()!] = carTypeArray.randomElement()!

Swift 3 - How to read a json output from an index that contains a string

I'm using an api to get some json information, here is an example what it looks like:
multimedia: [
{
url: "small.jpg"
format: "small"
},
{
url: "medium.jpg"
format: "medium"
},
{ url: "large.jpg"
format: "large"
}
]
so as you can see the multimedia container has many image urls with different sizes, and I want to read only one of them for example only the url for the medium.jpg.
My code is something like this that reads the multimedia container first:
let randomImg = result[random]["multimedia"] as! [[String: AnyObject]]
Then I made another variable which reads the index I want:
let randomImgIndex = randomImg[1]
so when I try to get my final string I get error:
let finalImgUrl = randomImgIndex[random]["url"] as! String
Error: Cannot subscript a value of type '[String : AnyObject]' with an index of type 'Int'
I am very new to swift so I'm totally lost.
randomImgIndex is already the desired dictionary.
Change:
let finalImgUrl = randomImgIndex[random]["url"] as! String
to:
let finalImgUrl = randomImgIndex["url"] as! String
On a side note, you need to stop using all of those ! and as! operators. Your app will crash if the data isn't exactly as expected. Code defensively when you are obtaining data beyond your control.

Swift picker array error

var pickerData: [[String]] = [String]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Connect data:
self.gothramPicker.delegate = self
self.gothramPicker.dataSource = self
pickerData = [
[["A"],["i","ii","iii"]],
[["B"],["iv","v","vi","vii"]]
]"
getting error of Contextual type 'String' cannot be used with array literal. 
my picker has two sections and each item if selected in the first picker has its own subdivisions to select from the second picker.
I want to use Array in Array and each main array has subarrays of different list. When I select first array in the picker it should show only the subitems of the particular Array item. For which when I add the double Brackets, I am getting the error. Also please let me know any error in the code
#sureshtrb , I am not posting answer because you don't asked question here. Frankly, you are troubling in Syntax understanding only.
You were declaring picketData of type Array([]) that contains array of string[[String]], and by putting ["A"] in place of string, you are adding an array ["A"] in place of String "A".
As per your real problem, I suggest you to go with 2 diff array or use dictionary.
The below code compiles.
var pickerData: [[String]] = [[String]]()
override func viewDidLoad() {
super.viewDidLoad()
pickerData = [
["A","i","ii","iii"],
["B","iv","v","vi","vii"]
]
}

Swift 3 - invalid JSON object of [[String: Any]]

I have this instance:
var commands = [[String: Any]]()
After some calculations, its result is:
[["command": 50022, "homes": [["gateways": [["mac": "845DD74B405E", "services": [["iid": 9, "name": "Some name"]], "aid": 1]], "name": "H1"]]], ["command": 50025, "services": [["mac": "845DD74B405E", "iid": 9, "aid": 1, "new_name": "Some name"]]]]
I want to convert it (commands) to JSON using SwiftyJSON:
let json = JSON(commands)
print(json) // "unknown"
but the result is always unknown.
Then I check the validity of commands to make sure it is JSON-convertable. But I got false with JSONSerialization.isValidJSONObject(commands), which is unexpected!
Do you have any ideas why commands (array of Dictionary) is NOT a valid JSON object?
Thanks
The problem in my commands is at the integer numbers, 50022 and 50025. In my code, they are defined in an enum of UInt32. And when I copied them to a playground to verify, Swift converts it to Int. That is why I always succeed in playground.
Back to my code, Swift 3 expects a number to be an Int in order to convert it to a JSON object successfully. Swift 2 does not have this behavior.
So, after I change my enum define from UInt32 to Int, it just works beautifully!
Thanks everyone.

Generating a JSON-Array and converting it to a Base64-String

I'm trying to create a Base64-String in Swift. I have an example of a Base64-encoded string and its array-counterpart. My problem now is, that I don't know how I get an equivalent array to the one which is given in the example.
Because I didn't want to mess around in my XCode-project I did the following in a playground.
given array:
{"WHERE":{"Class":"%3f","Location":"3b"},"ORDER":["Day ASC","Location DESC"]}
given Base64-string:
eyJXSEVSRSI6eyJDbGFzcyI6IiUzZiIsIkxvY2F0aW9uIjoiM2IifSwiT1JERVIiOlsiRGF5IEFTQyIsIkxvY2F0aW9uIERFU0MiXX0=
First I'm decoding the example-string
let str = "eyJXSEVSRSI6eyJDbGFzcyI6IiUzZiIsIkxvY2F0aW9uIjoiM2IifSwiT1JERVIiOlsiRGF5IEFTQyIsIkxvY2F0aW9uIERFU0MiXX0="
let data = NSData(base64EncodedString: str, options: NSDataBase64DecodingOptions(rawValue: 0))
do {
let result = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
} catch let error {
print(error)
}
//"result" is ["WHERE": ["Class": "%3f", "Location": "3b"], "ORDER": ["Day ASC", "Location DESC"]]
Below I'm trying to reproduce the string from above
var array = [String : AnyObject]()
var arrayPartA = [String : String]()
arrayPartA["Class"] = "%3f"
arrayPartA["Location"] = "3b"
array["ORDER"] = ["Day ASC", "Location DESC"]
array["WHERE"] = arrayPartA
array //The playground says that "array" is ["ORDER": ["Day ASC", "Location DESC"], "WHERE": ["Class": "%3f", "Location": "3b"]]
//"ORDER" and "WHERE" are switched but I don't get them to be at the right position
let utf8str2: NSData = String(array).dataUsingEncoding(NSUTF8StringEncoding)!
let encodedStr = utf8str2.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
//Here "encodedStr" is WyJPUkRFUiI6ICgKICAgICJEYXkgQVNDIiwKICAgICJMb2NhdGlvbiBERVNDIgopLCAiV0hFUkUiOiB7CiAgICBDbGFzcyA9ICIlM2YiOwogICAgTG9jYXRpb24gPSAzYjsKfV0=
//but it should be eyJXSEVSRSI6eyJDbGFzcyI6IiUzZiIsIkxvY2F0aW9uIjoiM2IifSwiT1JERVIiOlsiRGF5IEFTQyIsIkxvY2F0aW9uIERFU0MiXX0=
I would be glad if someone could explain to me what I'm doing wrong and how I can reproduce the given Base64-string.
Since I'm new to this website I apologize in advance for wrong layout or other possible conventions I don't know.
Could you try this please? Is this what you wanted to do? It should convert a Dictionary to base64 String
func jsonToBaseString (yourJSON: [String: String]) -> String? {
do {
let jsonData = try JSONSerialization.data(withJSONObject: yourJSON, options: JSONSerialization.WritingOptions.prettyPrinted)
return
jsonData.base64EncodedString(options: .endLineWithCarriageReturn)
} catch {
return nil
}
}
Dictionary is Swifts JSON representation...
Two important things to understand:
What you are calling an array is not an array, it's a JSON dictionary (containing an array for the ORDER key).
Be careful not to confuse the syntax of arrays and dictionaries between Swift and JSON.
In Swift, an array: [0, 1], a dictionary: ["a":0, "b":1].
In JSON, an array: [0, 1], a dictionary: {"a":0, "b":1}.
A Swift dictionary is an unordered collection. There's no "position" for key-value pairs.
You'll need to change several things:
Your input string (not serialized) is not an array, but a JSON object.
Try constructing your string with a proper JSON library, such as SwiftyJSON.
String(array) is not enough to consistently convert your objects to strings. You should use a JSON serializer (such as SwiftyJSON json.rawString()).
let follow recommendation to use some json serialization, but take in account that
{
"alfa": 1,
"beta": true
}
and
{"beta":true,"alfa":1}
represents in JSON notation the same object even though their string representation ( doesn't matter if base64 encoded or not ) are different.

Resources