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"]
Related
I'm trying to access an array response within array this is how I'm getting the friends array successfully
let url = URL(string: "http://xyz/api/get-friends-in-meetings")
AF.request(url!, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: headers).responseJSON{ response in
switch response.result {
case .success:
let responseValue = response.value as! NSDictionary
let friends: [NSDictionary] = responseValue["friends"] as! [NSDictionary]
//here I want to store the "meeting array so that I can use it later"
break
case .failure(let error):
print(error)
break
}
}
This is the JSON response
{
"status": 0,
"message": "Friends found.",
"friends": [
{
"id": 24,
"name": "XYZ",
"email": "Z#Y.Z",
"meetings": [
{
"meeting_with": "X",
"meeting_person_screen_name": "Y",
"meeting_purpose": "Z",
}
]
}
]
}
how do I get the "meetings" array which is within the "friends" array? I have tried the same way as I did for friends but it show an error No exact matches in call to subscript
First you need to define these structs:
struct DataResult : Decodable {
let status: Int
let message: String
let friends: [FriendsResult]
}
struct FriendsResult : Decodable {
let id: Int
let name: String
let email: String
let meetings: [MeetingsResult]
}
struct MeetingsResult: Decodable {
let meeting_with: String
let meeting_person_screen_name: String
let meeting_purpose: String
}
So after that we need the JSON Example:
// Meetings
let meeting1: [String: Any] = [
"meeting_with": "X",
"meeting_person_screen_name": "Y",
"meeting_purpose": "Z"
]
// Friends
let friend1: [String: Any] = [
"id" : 24,
"name": "XYZ",
"email": "x#y.z",
"meetings": [meeting1]
]
let friend2: [String: Any] = [
"id" : 25,
"name": "John Doe",
"email": "jd#x.doe",
"meetings": [meeting1]
]
// Main JSON
let jsonExample: [String : Any] = [
"status": 0,
"message": "Friends found.",
"friends": [friend1, friend2]
]
Well, we continue to validate the JSON and decode to "DataResult":
let valid = JSONSerialization.isValidJSONObject(jsonExample)
if valid {
do {
let dataResult = try JSONSerialization.data(withJSONObject: jsonExample, options: JSONSerialization.WritingOptions())
let dataDecode = try JSONDecoder().decode(DataResult.self, from: dataResult)
let jsonString = String(data: dataResult, encoding: .utf8)
print("JSON: \(String(describing: jsonString))")
if dataDecode.friends.count > 0 {
// Get first friend you should use guard
let friend = dataDecode.friends[0]
let meeting = friend.meetings[0]
print("\(friend.name)")
print("\(meeting.meeting_with)")
}
}
catch let error {
print("ERROR: \(error.localizedDescription)")
}
}
else {
print("Invalid JSON")
}
I have a dictionary which I want to append some items.
**This is my dictionary which I want to achieve: **
let parameters: [String: Any] = [
{
"ResultsList": [{
"UserId": "b806e283-066f-4081-aafe-1fe216a57c35",
"FriendUserId": "7a2ec150-cdb3-4600-84f8-2dab970bfa0c",
"TransferDate": "2017-11-23",
"UserAnswers": [{
"AnswerId": "b7562603-614d-11e7-a7e0-484d7ee0cd26",
"LastAnsweredDate": "2017-11-23",
"QuestionId": "0b60f35e-5d80-11e7-a7e0-484d7ee0cd26"
},
{
"AnswerId": "b7562603-614d-11e7-a7e0-484d7ee0cd26",
"LastAnsweredDate": "2017-11-23",
"QuestionId": "0b60f35e-5d80-11e7-a7e0-484d7ee0cd26"
}
]
}]
}
]
And this is my current dictionary which I want to make the loop and add the items.
let parameters: [String: Any] = [
{
ResultsList: [
{
UserId: “b806e283-066f-4081-aafe-1fe216a57c35”
FriendUserId: “7a2ec150-cdb3-4600-84f8-2dab970bfa0c”
TransferDate: “2017-11-23”
UserAnswers: [
{
AnswerId: “b7562603-614d-11e7-a7e0-484d7ee0cd26"
LastAnsweredDate: “2017-11-23”
QuestionId : “0b60f35e-5d80-11e7-a7e0-484d7ee0cd26"
}
]
}
]
}
]
I have 3 arrays which I want to loop through and append to the dictionary
var AnswerId = [ “b7562603-614d-11e7-a7e0-484d7ee0cd26", “aasdaas-614d-11e7-a7e0-484d7ee0cd26", “b756asd03-614d-11e7-a7e0-484d7ee0cd26"]
var LastAnsweredDate = [“2017-11-23”, “2017-11-23”, “2017-11-22”]
var QuestionId = [“0b60f35e-5d80-11e7-a7e0-484d7ee0cd26",“asdasd-5d80-11e7-a7e0-484d7ee0cd26",“asdasd-5d80-11e7-a7e0-484d7ee0cd26"]
Can someone please help to achieve this result?
I need to create the following json in swift 3 and I don't want to use external libraries.
I tried this answer but I'm using custom classes (store and product) inside the array, so it doesn't work.
"order":
[{
"store": 1,
"product": [
{
"id": 1,
"quantity": 1
},
{
"id": 2,
"quantity": 5
}]
},
{
"store": 4,
"product": [ {
"id": 1,
"quantity": 1
},
{
"id": 3,
"quantity": 1
}]
}]
}
Pretty sure you can accmoplish this with the following:
1) Create a toJSON() function in your object's class
2) Make a dictionary in this object that stores the properties and their values.
Here's an example of a couple of small classes based off your json example:
class Order {
var store: Store!
var products: [Product]!
init(store: Store, products: [Product]) {
self.store = store
self.products = products
}
func toJSON() -> [String : Any] {
var dictionary: [String : Any] = [:]
dictionary["store"] = store.toJSON()
var productsDictionary: [Int : Any] = [:]
for index in 0...self.products.count - 1 {
let product: Product = products[index]
productsDictionary[index] = product.toJSON()
}
dictionary["product"] = productsDictionary
return dictionary
}
}
class Store {
var id: Int!
init(id: Int) {
self.id = id
}
func toJSON() -> [String:Any] {
var dictionary: [String : Any] = [:]
dictionary["id"] = self.id
return dictionary
}
}
class Product {
var id: Int!
var quantity: Int!
init(id: Int, quantity: Int) {
self.id = id
self.quantity = quantity
}
func toJSON() -> [String:Any] {
var dictionary: [String : Any] = [:]
dictionary["id"] = self.id
dictionary["quantity"] = self.quantity
return dictionary
}
}
3) Follow the example link you posted
NSJSONSerialization.dataWithJSONObject(order.toJSON(), options: nil, error: nil)
Add a method to your classes called "ToDictionary" that returns a dictionary hand-coded with your fields and values. Then just call NSJSONSerialization on that dictionary. Under ObjC you could use reflection, but that's not here yet...
I have tier to get all value from this jsonResult i want array from this like "projectArray","msg","msg2" and string like "output" ,"output_prg" i only get first array value how to get other values?
This is my result
{
"project": [{
"name": [{
"sac": "sachin",
"sag": "sagar"
}]
}, {
"output": " true",
"msg1": [{
"emp": "001",
"empname": "sachin"
}, {
"emp": "002",
"empname": "sagar"
}]
}, {
"output_prg": " true",
"msg2": [{
"id": "1",
"pr_code": "SD"
}, {
"id": "002",
"pr_code": "SJ"
}]
}]
}
This is my code
if let array = response.result.value as? NSDictionary
{
print(array)
let mainArray = array["project"] as? [[String:Any]]
print(mainArray!)
for item in mainArray!
{
print(item)
let status = item["name"]
print(status!)
}
}
Thank you in advance
Try This---->
//to get JSON return value
if let array = response.result.value as? NSDictionary
{
print(array)
let mainArray = array["project"] as? [[String:Any]]
print(mainArray?.count as Any)
if (mainArray?.count)!>0
{
let name = mainArray?[0]
let project_status = name?["name"] as? [[String:Any]]
print(name!)
}
if (mainArray?.count)!>1
{
let output = mainArray?[1]
print(output!)
}
if (mainArray?.count)!>2
{
let output_prg = mainArray?[2]
let Output_getProject = output_prg?["output_prg"]
}
}
}
Happy Coading :-)
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.