Hi I’m a beginner at programming and I followed a tutorial online to parse information from a Json file. In order to get an URL link, I created a local server that contains a json file. When I start the program I get a mistake.
Called Thread 2: signal SIGABRT for the code snippet
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]
Google says there is a disconnected outlet, but the outlets in my code are connected.
There are also multiple error warnings, and google says there is a problem with an array and I have to set it to NSDictionary
, but I never declared any variable as an array or a dictionary.
Could not cast value of type '__NSArrayM' (0x7fff80919120) to 'NSDictionary' (0x7fff809193b0).
2021-06-30 22:01:07.257592+0200 Booknerd3.0[71572:3475394] Could not cast value of type '__NSArrayM' (0x7fff80919120) to 'NSDictionary' (0x7fff809193b0).
Could not cast value of type '__NSArrayM' (0x7fff80919120) to 'NSDictionary' (0x7fff809193b0).
CoreSimulator 757.5 - Device: iPhone 8 (A2400EB4-8BA3-4297-9DF3-1743AA0BB7E4) - Runtime: iOS 14.5 (18E182) - DeviceType: iPhone 8
Json file:
{
"books":
[
{
"author": "Chinua Achebe",
"country": "Nigeria",
"imageLink": "https://s3.amazonaws.com/AKIAJC5RLADLUMVRPFDQ.book-thumb-images/ableson.jpg",
"language": "English",
"link": "https://en.wikipedia.org/wiki/Things_Fall_Apartn",
"pages": 209,
"title": "Things Fall Apart",
"year": 1958
},
{
"author": "Hans Christian Andersen",
"country": "Denmark",
"imageLink": "https://s3.amazonaws.com/AKIAJC5RLADLUMVRPFDQ.book-thumb-images/ableson2.jpg",
"language": "Danish",
"link": "https://en.wikipedia.org/wiki/Fairy_Tales_Told_for_Children._First_Collection.n",
"pages": 784,
"title": "Fairy tales",
"year": 1836
}
]
}
My view controller
import UIKit
class MainScreenViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableview: UITableView!
var books: [Books]? = []
override func viewDidLoad() {
super.viewDidLoad()
fetchArticle()
}
func fetchArticle(){
let urlRequest = URLRequest(url: URL(string: "http://localhost:3000/books")!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data,response,error) in
if error != nil {
print(error)
return
}
self.books = [Books]()
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]
if let booksFromJson = json["books"] as? [[String : AnyObject]]{
for bookFromJson in booksFromJson {
let book = Books()
if let title = bookFromJson["title"] as? String, let author = bookFromJson["author"] as? String, let imageLink = bookFromJson["imageLink"] as? String {
book.author = author
book.title = title
book.imageLink = imageLink
}
self.books?.append(book)
}
}
DispatchQueue.main.async {
self.tableview.reloadData()
}
} catch let error {
print(error)
}
}
task.resume()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "bookCell", for: indexPath) as! BookCell
cell.title.text = self.books?[indexPath.item].title
cell.author.text = self.books?[indexPath.item].author
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.books?.count ?? 0
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
}
}
2
Answers
A lot of force unwraps, assumptions about the type. Just don’t if you want to have a stable app. Most likely you’re looking for usage of
Decodable
. You can declare two structs to reflect the JSON schema.For your example it would be:
Which can be used in your code with few modifications.
No force unwraps, no guessing, zero crashes :). This approach lets you have custom decoding strategies as well. You can read more about
Codable (Decodable & Encodable)
hereShort answer your Json is a Dictionary that contains a key with a value of array of dictionary. When you decode you’re saying it will be a dictionary key of books and value of array of array of dictionary.
an array of dictionary is
more specifically in your case