How do i declare the datatype for the below multidimensional array
settings = [
“person" : [
“name”:"bing",
"status”:"done",
],
“flags" : [
“moved" :true
]
]
tried with var settings = [String](), var settings = [String[String:String] but did not work
After correcting all the small mistakes (you're using “ instead of ")
let settings = ["person": ["name": "bing", "status": "done"], "flags": ["moved": true]]
Alt clicking settings is showing:
let settings: [String : Dictionary<String, NSObject>]
But you could also declare it as [String: [String: AnyObject]]
Related
Given this
var applicationPayload =
[
"main": [
"key1": "value1",
"key2": [
"inside1": "insideValue1"
]
]
]
How can I append or add something inside key2 property.. I'd like the result to be something like this
[
"main": [
"key1": "value1",
"key2": [
"newInside2": "newInsideValue2",
"inside1": "insideValue1"
]
]
]
I tried doing this does not seems to work
applicationPayload["main"]["key2"]["newInside2"] = "newInsideValue2"
You could create a variable containing the current value of key2 and modify that before rewriting it back into the original dictionary:
import Foundation
var applicationPayload =
[
"main": [
"key1": "value1",
"key2": [
"inside1": "insideValue1"
]
]
]
print("Before: \(applicationPayload)")
var key2Value = applicationPayload["main"]?["key2"] as! [String: String]
key2Value["newInside2"] = "newInsideValue2"
applicationPayload["main"]?["key2"] = key2Value
print("After: \(applicationPayload)")
Output:
Before: ["main": ["key1": "value1", "key2": ["inside1": "insideValue1"]]]
After: ["main": ["key1": "value1", "key2": ["inside1": "insideValue1", "newInside2": "newInsideValue2"]]]
You can try for easy access/assign with keyPath
// get value of key2
var res = applicationPayload[keyPath:"main.key2"] as! [String:Any]
// add the other key
res["newInside2"] = "newInsideValue2"
// mutate key2
applicationPayload[keyPath:"main.key2"] = res
For more about keypaths check https://oleb.net/blog/2017/01/dictionary-key-paths/
I am trying to my code Swift 2 to Swift 3 but I can not convert following code.
When I use Any instead of AnyObject I am getting error like: Contextual type 'Any' cannot be used with array literal in "items:" part.
When I user AnyObject and then use the "name:" part as AnyObject getting error like: Contextual type 'AnyObject' cannot be used with array literal
I could not find the best solution for it.
How can I do it?
var menus: [[String: AnyObject]] {
return [
["name": NSLocalizedString("General", comment: ""),
"items": [
MenuItem(icon: UIImage.fontAwesomeIcon(FontAwesome.Heart, textColor: TubeTrends.Settings.foregroundColor, size: TubeTrends.Settings.menuIconSize), title: NSLocalizedString("Favorites", comment: ""), action: { (indexPath) -> Void in
self.navigationController?.pushViewController(self.favoritesVideoListVC(), animated: true)
}),
]
]
In Swift 3 heterogenous literal collection types must be annotated explicitly, for example
var menus: [[String: Any]] {
let dict : [String:Any] = ["name": NSLocalizedString("General", comment: ""),
"items": [
MenuItem(icon: UIImage.fontAwesomeIcon(FontAwesome.Heart, textColor: TubeTrends.Settings.foregroundColor, size: TubeTrends.Settings.menuIconSize), title: NSLocalizedString("Favorites", comment: ""), action: { (indexPath) -> Void in
self.navigationController?.pushViewController(self.favoritesVideoListVC(), animated: true)
}),
]
]
return [dict]
}
I am currently having a bad time with type casting while fetching some data.
Here is the data I have in the debug console:
(7, ["name": Doe, "id": 2042, "website": http://somedomaine.com/, "logo": http://somedomaine.com/img/, "category_id": 33, "category": Institutional partners, "order": 7])
I am sure this is really obvious, but I can't figure out how to access to data like name or id and it is giving me headache. This is what I have done:
let section = ( index as NSIndexPath ).section + 1 as Int
let row = ( index as NSIndexPath ).row as Int
let sectionContent = posts![ section ] as? Array< Any >
let entry = ( sectionContent?[ row ] as AnyObject )
After that, the best I can get is nil!
Here is a little more details: the posts variable is initiated at the top of the class like so:
internal var posts: [ Int: AnyObject ]?
The data are parsed like this (the original data come from a json feed which is fine):
func parsePosts( posts: [ Dictionary< String, AnyObject > ] ) -> ( [ Int: AnyObject ], Int ) {
var theCategories = [ Int : AnyObject ]()
var theSponsors = [ Int : AnyObject ]()
var theDict = [ Int : Array< Any > ]()
for item in posts {
let itemID = item[ "id" ] as! Int
let sponsorMeta = item[ "sponsor_meta" ]
let category = sponsorMeta?[ "category" ] as? String
let title = item[ "title" ]
let name = title?[ "rendered" ] as? String
if !( category ?? "" ).isEmpty {
let order = Int( ( sponsorMeta?[ "order" ] as? String )! )
let categoryID = sponsorMeta?[ "category_id" ] as! Int
let categoryOrder = sponsorMeta?[ "category_order" ] as! Int
let website = sponsorMeta?[ "url" ] as? String
let logo = sponsorMeta?[ "logo" ] as? [ String: Any ]
let logoSizes = logo?[ "sizes" ] as? [ String: Any ]
let imgUrl = logoSizes?[ "medium_large" ] as? String
let sponsor = [ "id": itemID, "name": ( name )! as String, "logo": imgUrl! as String, "website": ( website )! as String, "category": category!, "order": order!, "category_id": categoryID ] as [ String : Any ]
let category = [ "name": category!, "order": categoryOrder ] as [ String : Any ]
theCategories[ categoryID ] = category as AnyObject
theSponsors[ itemID ] = sponsor as AnyObject
}
}
for ( k, value ) in theCategories {
let categoryOrder = value[ "order" ] as! Int
var catDict = [ Int : [ String: AnyObject ] ]()
for ( _, element ) in theSponsors {
let sponsorCategoryID = element[ "category_id" ] as! Int
if sponsorCategoryID == k {
let sponsorOrder = element[ "order" ] as! Int
catDict[ sponsorOrder ] = element as? [ String : AnyObject ]
}
}
let sortedCat = catDict.sorted( by: { $0.0 < $1.0 } )
theDict[ categoryOrder ] = sortedCat
}
let sortedDict = theDict.sorted( by: { $0.0 < $1.0 } )
var finalDict = [ Int: AnyObject ]()
for ( t, v ) in sortedDict {
finalDict[ t ] = v as AnyObject?
}
return ( finalDict, theCategories.count )
}
I am sure it is just a small thing but I have been playing for hours with casting types and I haven't found a solution.
Does anybody have a suggestion? It will be much appreciated. Thanks!
I see that you have created a tuple and in order to access that data from that tuple I would suggest this approach
let posts = (7, dataDictioanry: ["name": "Doe", "id": 2042, "website": "http://somedomaine.com/", "logo": "http://somedomaine.com/img/", "category_id": 33, "category": "Institutional partners", "order": 7])
posts.dataDictioanry["name"]
I want to get Addresses from profile dictionary,but I got the error "type any? has no subscript members"
var address:[[String : Any]] = [["Address": "someLocation", "City": "ABC","Zip" : 123],["Address": "someLocation", "City": "DEF","Zip" : 456]]
var profile:[String : Any] = ["Name": "Mir", "Age": 10, "Addresses": address]
profile["Addresses"][0] <-----------------type any? has no subscript members
How can I fix it and get the address? Thanks a lot.
When you subscript profile with "Addresses", you're getting an Any instance back. Your choice to use Any to fit various types within the same array has caused type erasure to occur. You'll need to cast the result back to its real type, [[String: Any]] so that it knows that the Any instance represents an Array. Then you'll be able to subscript it:
func f() {
let address: [[String : Any]] = [["Address": "someLocation", "City": "ABC","Zip" : 123],["Address": "someLocation", "City": "DEF","Zip" : 456]]
let profile: [String : Any] = ["Name": "Mir", "Age": 10, "Addresses": address]
guard let addresses = profile["Addresses"] as? [[String: Any]] else {
// Either profile["Addresses"] is nil, or it's not a [[String: Any]]
// Handle error here
return
}
print(addresses[0])
}
This is very clunky though, and it's not a very appropriate case to be using Dictionaries in the first place.
In such a situation, where you have dictionaries with a fixed set of keys, structs are a more more appropriate choice. They're strongly typed, so you don't have to do casting up and down from Any, they have better performance, and they're much easier to work with. Try this:
struct Address {
let address: String
let city: String
let zip: Int
}
struct Profile {
let name: String
let age: Int
let addresses: [Address]
}
let addresses = [
Address(
address: "someLocation"
city: "ABC"
zip: 123
),
Address(
address: "someLocation"
city: "DEF"
zip: 456
),
]
let profile = Profile(name: "Mir", age: 10, addresses: addresses)
print(profile.addresses[0]) //much cleaner/easier!
You should re-think how you've chosen to construct adress and profile; see e.g. Alexander Momchliov's answer.
For the technical discussion, you could extract the Any members of profile that you know to contain [String: Any] dictionaries wrapped in an Any array; by sequential attempted type conversion of profile["Addresses"] to [Any] followed by element by element (attempted) conversion to [String: Any]:
if let adressDictsWrapped = profile["Addresses"] as? [Any] {
let adressDicts = adressDictsWrapped.flatMap{ $0 as? [String: Any] }
print(adressDicts[0]) // ["Zip": 123, "City": "ABC", "Address": "someLocation"]
print(adressDicts[1]) // ["Zip": 456, "City": "DEF", "Address": "someLocation"]
}
or, without an intermediate step ...
if let adressDicts = profile["Addresses"] as? [[String: Any]] {
print(adressDicts[0]) // ["Zip": 123, "City": "ABC", "Address": "someLocation"]
print(adressDicts[1]) // ["Zip": 456, "City": "DEF", "Address": "someLocation"]
}
But this is just a small lesson in attempted typed conversion (-> don't do this).
I agree that if you rethink your design as suggested earlier. For discussion sake you can perform the following to achieve what you are seeking.
var address:[[String : Any]] = [["Address": "someLocation", "City": "ABC","Zip" : 123],["Address": "someLocation", "City": "DEF","Zip" : 456]]
var profile:[String : Any] = ["Name": "Mir", "Age": 10, "Addresses": address]
if let allAddresses = profile["Addresses"] as? [[String:Any]] {
print("This are all the address \(allAddresses[0])")
}
MY JSON:
{
"response" : {
"start" : 0,
"docs" : [
{
"enrollmentId" : [
"KAR\KDF6"
],
"fieldName2" : [
"Languages"
],
"locality" : [
"Boret"
],
"active" : [
true
],
"sex" : [
"Male"
],
"latitude" : [
12.457
],
"city" : [
"Booer"
],
"imageData" : [
"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABkCAYAAAAlg3YKAAA1wklEQVR4AcWd95Nc13XnT+c405MHMyACARDMoCxSibYsrWtXP7h2\/1XXbklea4vyWlW2apUp0SbBIJIgEQaYgMk9nXs\/n\/umgUEgCUis8gN7uvv1fffd+70nn3Mfc3fu3BnHf9IxuXHua76\/\/X5dfRbfeeedr3l4X93dZAJjZpFzKvw3OZcf8fn4e+ppPE6THeeO3\/kxAUsbP+QiH\/l0YsxX\/nF+lBtTOn4857H+MY7zIDhiY2AsKKWFzuAiRIOJfGbptjDCQO7GkRBVMaOBCPBMCJC9JvGY7ZTQSJfwq8ErLBmxrLTX4av1lZYb+ykg+XTEKbGZjGSfdIvocPCWCQAFaHzdzCbTnw3DMXAGqO68hpIT\/MiXnrJsL5\/atYzFTD+gS9RAmwfBor4xAg2cj\/cYlU6x42DcYZnpbVJGl4\/U\/X0ITsNeIaJz4BwflOjgyDybcMqNz+7oEBtgSNA0kwCU4alt85w0TSD\/yx42Qs8u5pm6X\/e4Gkfgyq1mn6wauhuvTkXhdAvc9F8n2yPzxln1Cf7GIEgFNsGaemh3P+8x6OxmIHt0ZNszmlhHCWYh9kFSgBWZQA4woXxc4UByOu1bIvUaSl+5AOfncuE7fE4Xl4WRqE79z3\/wOcrF6q09MBWgAAAABJRU5ErkJggg=="
],
"fieldValue2" : [
"English, Hindi, Kannada"
],
"fieldValue1" : [
"11 years"
],
"state" : [
"Kerr"
],
"id" : "sdffsdfsdf",
"email" : [
"me#some.com"
],
"longitude" : [
77.552492
],
"firstName" : [
"Prashya"
],
"_version_" : 145434759168,
"experience" : [
12
],
"caseTypes" : [
"some some"
],
"lastName" : [
"Bhaer"
],
"mode" : [
"Lawyer"
],
"fieldName1" : [
"Experience"
]
},
{
"state" : [
"Rater"
],
"languages" : [
"English",
"Hindi",
"Kannada"
],
"lastName" : [
"K"
],
"firstName" : [
"Rresr"
],
"sex" : [
"Male"
],
"caseTypes" : [
"So many"
],
"enrollmentId" : [
"KARdsfs"
],
"mobile" : [
98453445
],
"id" : "Rajfsdsg",
"imageData" : [
"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFcAAABkCAYAAADzJqxvAAAgAElEQVR4XjS9ebBv2VkdtvY+8zm\/8c5vfj2r1VJrQgNEiMkYi0m2kmAbE3DhlAPEqcSuciquVIrgMhCTgF1BQgSMkW0EthkEGCQQIAQCScgSaqk19Ot+3W++872\/8Yz7nL1T6zvP\/Qelbu793XP28H3rW2t9308d3P2iaxEggIdivcBgmCDQPirTwA8UqlIhiDV8pdB0JZz2AevBg4+mrgHTAoHGMElR1DX8MIJvLKzXojMafgg0dQMFwPM9dI2D8g06aHidD4sWjXYAFBLto1WAcw3asoNrLaxSsFCIAw1oD0p1aIyF5\/nwPaCrOvhRgLyukIUx6qaCFwZo8gpRmuDC9YtQqoVdnsM2FaraomkrFMbBMw424ucEcI3hA6IuGwSJj6Zr0Rog8Bw8P0DTOrTGwnVAGFh0ms9p4Ssf4LvWCspqtNpBKeD85BTq+OBFZ42DcgodOvi+B2NbaOcjgsa6qRFFGs4CbeMQRB5MW8M0LbIgg+9ZlMbJH3D8DNPBtwZhNkDTVEiyEcqmhG4VoshDVXcI\/QCds2iqHHGSwlmH2vL3W3g6hIKCaVv4AdBw84xFFPnouk7+hlVA11l4yke3+cSnLBW0vLKiqrrJc3fu6t12JWqm5qdnbeWJUJF8OipsQ8UJGq6cvVNjU9MWIbHQUeNhbJxGDSYVn0TPQUv4GxJKG0Skpv+tuHWBqbXQ6WSyOjA\/VtRCUqZYrH4UUv2\/ziJ\/f\/aiwX2jbsXKz3ga\/aN+4CG28vb9o27Fys94Gv2jfuAhtvL2\/aNuxcrPeBr\/g2M2m9YyIB6mAAAAABJRU5ErkJggg=="
],
"active" : [
true
],
"mode" : [
"Lawyer"
],
"city" : [
"Bangalore"
],
"_version_" : 15214536,
"email" : [
"me#me.com"
],
"experience" : [
18
],
"locality" : [
"bajaj"
]
}
],
"numFound" : 2
},
"responseHeader" : {
"status" : 0,
"QTime" : 1,
"params" : {
"q" : "mode:(\"Lawyer\", \"CA\") AND active:true AND city:(\"Boret\") AND locality:(\"bajaj\") AND caseTypes:(\"fly fly\")",
"wt" : "json"
}
}
}
I've declared a global array private var items = [UIImage]() and private var cellsIsOpen = [Bool]() .
I'm converting the bas64 imageData strings obtained from JSON data and returning an array of UIImage like
public func loadimages(url: String!) -> [UIImage]{
let unsafe = url
var data1 = [UIImage]()
let bingo = NSURL(string: unsafe!)
Alamofire.request(.GET, bingo!)
.validate()
.responseJSON{ response in
switch response.result{
case .Success:
let json33 = JSON(data: response.data!)
let allImageStrings = json33["response"]["docs"].flatMap { $0.1["imageData"].first?.1}
for Bro in allImageStrings{
let url = NSURL(string: Bro.string!)
let data = NSData(contentsOfURL: url!)!
let image = UIImage(data: data)
data1.append(image!)
}
self.items = data1
//print(self.items.count)
case .Failure(let error):
print(error)
}
}
return data1
}
And in
override public func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print(self.items.count)
return self.items.count
}
the count is showing 0. The Array items is not getting appended AT ALL. How do I append it? I'm even trying to do
override public func viewDidLoad() {
// Do any additional setup after loading the view.
itemSize = CGSize(width: 214, height: 264)
super.viewDidLoad()
let gt: [UIImage] = loadimages("someurl&wt=json")
items.append(gt) //Error: Cannot convert value of type '[UIImage]' to expected argument type 'UIImage'
print(items.count)
}
And there it this function
func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
guard let cell = cell as? CollectViewCell else { return }
// var index = indexPath.row % 4
//let info = items
for item in items{
cell.backgroundImageView.image = item
}
cell.cellIsOpen(cellsIsOpen[indexPath.row], animated: false) //Here
collectionView.reloadData()
}
*Here, it crashes saying Index out of range.
Help Please?
It looks like your problem might be with your Alamofire request. Either it fails and so nothing it appended since you append under your success case, or you're trying to print the items before anything is loaded because it is an asynchronous request. Try appending an image under your failure case.
Also the reason you are getting the error "Cannot convert value of type '[UIImage]' to expected argument type 'UIImage' " is because you are trying to append an entire array to an array, when you need to just append a single element, in this case, a UIImage.
try this to test the size of your array instead
let gt: UIImage = UIImage()
items.append(gt)
print(items.count)
Alamofire is nice that it grabs the main thread in the callback making UI easy to update. Your first call to collectionView's dataSource methods will be before the request is done. However. calling collectionView.reloadData() after setting self.items should solve your issue.
case .Success:
let json33 = JSON(data: response.data!)
let data = json33["response"].stringValue.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
let json = JSON(data: data!)
let allImageStrings = json["docs"].flatMap { $0["imageData"].first?.stringValue }
for Bro in allImageStrings{
let imgString = Bro.stringByReplacingOccurrencesOfString("data:image/png;base64," , withString: "")
let imgData = imgString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
let image = UIImage(data: imgData)
data1.append(image!)
}
self.items = data1
//Add
self.collectionView.reloadData()
All data source methods are recalled on the collectionView when reloadData() is called so if you have successfully created images (This may be an underlying problem as well), you should get a count the next time these dataSource methods are called.
Try this
Replace this array type
var data1 = [UIImage]()
with this type of array for type safety sometime array not getting correct format so failed to append value
Use this Array:-
var data1 = [AnyObject]()
I hope this will help you.