https://jumpshare.com/v/Otai3BBXYwfvyz8jb53k
(Would be wise to view these to see structure of project)
Ok, so i'm following a tutorial that creates a UITableView with headers and then cell content.
The code worked and runs fine, Now I want to extend beyond that tutorial and dynamically load that content using alamofire and SwiftyJSON.
In the tutorial, the code used is like so:
func getSectionsFromData() -> [Sections] {
var sectionsArray = [Sections]()
let animals = Sections(title: "Animals", objects: ["Cats", "Dogs", "Birds", "Lions"])
sectionsArray.append(animals)
return sectionsArray
}
What I tried to do was:
Alamofire.request(.GET, url).validate().responseJSON { response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
for (_, subJson) in json {
for (year, content) in subJson {
let title = year
let objects = content
sectionsArray.append(Sections(title: title, objects: objects))
}
}
}
case .Failure(let error):
print(error)
}
}
If I print out the results they show in the console - so I know the getting and looping of the JSON works. I then added in
let title = year
let objects = content
sectionsArray.append(Sections(title: title, objects: objects))
But on this line:
sectionsArray.append(Sections(title: title, objects: objects))
I get this error:
cannot convert value of type 'JSON' to expected argument type '[String]'
Here is the JSON I am using:
{"posts": [
{
"Category1": [
"Post1cat1"
],
"Category2": [
"Post1cat2",
"Post2cat2"
]
}
]}
Can someone help me? I might be going in the wrong direction here I want to loop through the JSON and display the categories as headers and the posts in a cell of a table.
so, I changed the loop to:
for (_, subJson) in json {
for (index, data) in subJson {
for (title, objects) in data {
sectionsArray.append(Sections(title: title, objects: objects.self.arrayValue.map { $0.string!}))
}
}
}
Still no luck. When I add in some prints (under: sectionsArray.append) to test if there is data:
print("--")
print(title)
print(objects.self.arrayValue.map { $0.string!})
print(Sections(title: title, objects: objects.self.arrayValue.map { $0.string!}))
I get this result in the console:
--
Category1
["Post1cat1"]
Sections(headings: "Category1", items: ["Post1cat1"])
--
Category2
["Post1cat2", "Post2cat2"]
Sections(headings: "Category2", items: ["Post1cat2", "Post2cat2"])
Which shows that the information is there, however when I run the app there are still no results form he JSON just the originally defined section and cells above.
In second parsing method (after edit), you're iterating on array in last loop, so either you could create array there and add each element separately, as in example:
for (title, data) in subJson {
var elements: [String] = []
for (_, object) in data {
if let stringELement = object.rawString() {
elements.append(stringELement)
}
}
sectionsArray.append(Sections(title: title, objects: elements))
}
or if you prefer you can use casted raw array from JSON object as in this example:
for (_, subJson) in json["posts"] {
for (title, data) in subJson {
let optionalCastedObjects = data.arrayObject as? [String]
let unwrappedObjects = optionalCastedObjects ?? []
let section = Sections(title: title, objects: unwrappedObjects)
sectionsArray.append(section)
}
}
That should fix mentioned compilation issue.
But in the end remember that you're using async callback (in your GET request
) in synchronous getSectionsFromData
method. And you're always will return array before the values from that callback (clojure
) will append new data. That will cause, that you're never display the data that you fetched that way.
UPDATE
To do that you should refactor your getSectionsFromData
method as below.
func getSectionsFromData(completion: ([Sections]) -> ()) {
var sectionsArray = [Sections]()
Alamofire.request(.GET, url).validate().responseJSON { response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
for (_, subJson) in json["posts"] {
for (title, data) in subJson {
let optionalCastedObjects = data.arrayObject as? [String]
let unwrappedObjects = optionalCastedObjects ?? []
let section = Sections(title: title, objects: unwrappedObjects)
sectionsArray.append(section)
}
}
completion(sectionsArray)
}
case .Failure(let error):
print(error)
}
}
}
And relevant parts in your UITableViewController class.
var sections: [Sections] = []
override func viewDidLoad() {
super.viewDidLoad()
SectionsData().getSectionsFromData { [weak self](sections: [Sections]) -> () in
self?.sections = sections
self?.tableView.reloadData()
}
}
Your second loop is on the array object hence in that loop year
is index value and content
is the object at that index.
You need to implement an additional loop to fix the problem i.e:
for (_, subJson) in json {
for (index, data) in subJson {
for (title, objects) in data {
sectionsArray.append(Sections(title: title, objects: objects.arrayValue.map { $0.string!}))
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With