Hey All,
I am new to swift and i am having some issues with my JSON request. I am able to retrieve the data and i can output this into my ViewController but a part of the data i get back from my database is inside a multidimensional array. I want to take this data and loop through it. (sometimes this part contains 1 items, sometimes 2 sometimes 3 etc so its pretty dynamic)
I do everything programmaticly, so i use no storyboards.
This is a sample JSON response:
How can take the todo and create an array which i can loop through?
When i say
for item in json["todo"] {
print(item)
}
i get:
Value of optional type 'NSDictionary?' must be unwrapped to refer to member 'subscript' of wrapped base type 'NSDictionary'
My JSON
{
"firstname": "Wouter ",
"lastname": "SwiftySwift",
"profilepicture": "https://res.cloudinary.com/www-gipaa-nl/image/upload/w_400,h_400,c_crop,g_face,r_max,d_avatar.png,bo_25px_solid_white/w_200/v1551042302/images/1551035640e793a635f61e",
"aboutme": "This is test data, This is test data. ",
"acceptall": "1",
"todo": [
{
"id": "31",
"title": "Door",
"done": "0"
},
{
"id": "32",
"title": "Window",
"done": "0"
},
{
"id": "33",
"title": "test",
"done": "0"
},
{
"id": "34",
"title": "test",
"done": "0"
},
{
"id": "35",
"title": "test",
"done": "0"
},
{
"id": "36",
"title": "test",
"done": "0"
}
]
}
My Code
//
// MemberController.swift
// GIPAA
//
// Created by Wouter on 16/02/2019.
// Copyright © 2019 . All rights reserved.
//import Foundation
import UIKitextension UIImageView {
func dowloadFromServer(url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() {
self.image = image
}
}.resume()
}
func dowloadFromServer(link: String, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
dowloadFromServer(url: url, contentMode: mode)
}
}
class MemberController: UIViewController {lazy var scrollView: UIScrollView = { let view = UIScrollView() view.translatesAutoresizingMaskIntoConstraints = false view.contentSize.height = 2000 view.backgroundColor = UIColor.white return view }() let mainMenu: UIButton = { let image = UIImage(named: "menu.PNG") let l = UIButton(type: .system) l.addTarget(self ,action: #selector(openMenu), for: .touchUpInside) l.setBackgroundImage(image, for: .normal) return l }() let profileView: UIImageView = { let p = UIImageView() p.image = UIImage(named: "default.png") p.layer.borderWidth = 14.0 p.clipsToBounds = true p.layer.borderColor = UIColor.white.cgColor return p }() let memberTable: UITableView = { let m = UITableView() m.backgroundColor = orangeBanner m.separatorStyle = .none return m }() let memberInfoTable: UITableView = { let m = UITableView() m.backgroundColor = UIColor.white m.separatorStyle = .none return m }() let cell1: UITableViewCell = { let m = UITableViewCell() m.backgroundColor = UIColor.white return m }() let cell2: UITableViewCell = { let m = UITableViewCell() m.backgroundColor = grayBanner return m }() let mijnProfielField: UILabel = { let t = UILabel() t.text = "Mijn profiel" t.font = UIFont.boldSystemFont(ofSize: 18.0) t.textColor = UIColor.white return t }() let interesseButton: UIButton = { let h = UIButton() h.setTitle(" Interesses ", for: .normal) h.setTitleColor(UIColor.gray, for: .normal) h.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.left h.titleLabel?.font = h.titleLabel?.font.withSize(16) h.addTarget(self ,action: #selector(openInteresses), for: .touchUpInside) return h }() let compButton: UIButton = { let h = UIButton() h.setTitle("Competenties", for: .normal) h.setTitleColor(UIColor.gray, for: .normal) h.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.left h.titleLabel?.font = h.titleLabel?.font.withSize(16) return h }() let beoorButton: UIButton = { let h = UIButton() h.setTitle("Beoordelingen", for: .normal) h.setTitleColor(UIColor.gray, for: .normal) h.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.left h.titleLabel?.font = h.titleLabel?.font.withSize(16) return h }() let underMember=UIView() let nameField: UILabel = { let t = UILabel() t.font = UIFont.boldSystemFont(ofSize: 14.0) t.textColor = UIColor.black return t }() let aboutMeLabel: UILabel = { let t = UILabel() t.font = UIFont.boldSystemFont(ofSize: 10.0) t.numberOfLines = 18 t.textColor = UIColor.black t.backgroundColor = grayBanner return t }() let aboutmeTitle: UILabel = { let t = UILabel() t.text = "Over mij:" t.font = UIFont.boldSystemFont(ofSize: 12.0) t.textColor = UIColor.black return t }() let underTable=UIView() let ikStaOpenLabel: UILabel = { let t = UILabel() t.text = "Ik sta open voor alles" t.font = UIFont.boldSystemFont(ofSize: 14.0) t.numberOfLines = 18 t.textColor = UIColor.black return t }() let ikStaOpenButton: UIButton = { let h = UIButton() h.addTarget(self ,action: #selector(changeOpenVoor), for: .touchUpInside) h.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.left h.titleLabel?.font = h.titleLabel?.font.withSize(16) return h }() let intTitleTable: UITableView = { let m = UITableView() m.backgroundColor = orangeColor m.separatorStyle = .none return m }() let todoInfoTable: UITableView = { let m = UITableView() m.backgroundColor = UIColor.white m.separatorStyle = .none return m }() let todocell1: UITableViewCell = { let m = UITableViewCell() m.backgroundColor = orangeBanner return m }() let todocell2: UITableViewCell = { let m = UITableViewCell() m.backgroundColor = grayBanner return m }() let todoTitle: UILabel = { let t = UILabel() t.text = "To do list" t.font = UIFont.boldSystemFont(ofSize: 18.0) t.textColor = UIColor.white return t }() let addToDo: UIButton = { let h = UIButton() h.setTitle("+", for: .normal) h.addTarget(self ,action: #selector(addtodo), for: .touchUpInside) h.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.left h.titleLabel?.font = h.titleLabel?.font.withSize(26) h.setTitleColor(UIColor.white, for: .normal) return h }() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white let myUrl = URL(string: "https://gipaa.nl/app/member_json.php"); var request = URLRequest(url:myUrl!) request.httpMethod = "POST"// Compose a query string let accessToken: String? = KeychainWrapper.standard.string(forKey: "token") let userId: String? = KeychainWrapper.standard.string(forKey: "id") let postString = "userId=\(userId!)&token=\(accessToken!)"; request.httpBody = postString.data(using: String.Encoding.utf8); let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in if error != nil { print("error=\(error)") return } // You can print out response object // print("response = \(response)") //Let's convert response sent from a server side script to a NSDictionary object: do { let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary let firstname = json?["firstname"] let lastname = json?["lastname"] let profilepicture = json!["profilepicture"] let aboutme = json?["aboutme"] **var todo = json?["todo"]** DispatchQueue.main.async { self.nameField.text = "\(firstname!) \(lastname!)" if profilepicture is NSNull { }else{ self.profileView.dowloadFromServer(link: profilepicture! as! String, contentMode: .scaleAspectFill) self.view.addSubview(self.profileView) } if aboutme is NSNull { self.aboutMeLabel.text = "Geen informatie" }else{ self.aboutMeLabel.text = "\(aboutme!)" } } } catch { print(error) } } task.resume() setupScrollView() } override func viewWillLayoutSubviews() { profileView.layer.cornerRadius = profileView.frame.size.width / 2 } private func setupScrollView(){ view.addSubview(scrollView) scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true scrollView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true scrollView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true scrollView.keyboardDismissMode = .onDrag scrollView.isScrollEnabled = true // Do any additional setup after loading the view let imageView = UIImageView(frame: CGRect(x: 10, y: 5, width: 150, height: 50)) imageView.image = UIImage(named: "main.PNG") scrollView.addSubview(imageView) scrollView.addSubview(mainMenu) mainMenu.translatesAutoresizingMaskIntoConstraints = false mainMenu.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 5).isActive = true mainMenu.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -16).isActive = true mainMenu.heightAnchor.constraint(equalToConstant: 50).isActive = true mainMenu.widthAnchor.constraint(equalToConstant: 50).isActive = true view.addSubview(memberTable) memberTable.translatesAutoresizingMaskIntoConstraints = false memberTable.topAnchor.constraint(equalTo: mainMenu.bottomAnchor, constant: 10).isActive = true memberTable.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true memberTable.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true memberTable.heightAnchor.constraint(equalToConstant: 50).isActive = true view.addSubview(mijnProfielField) mijnProfielField.translatesAutoresizingMaskIntoConstraints = false mijnProfielField.topAnchor.constraint(equalTo: mainMenu.bottomAnchor, constant: 5).isActive = true mijnProfielField.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10).isActive = true mijnProfielField.widthAnchor.constraint(equalToConstant: 120).isActive = true mijnProfielField.heightAnchor.constraint(equalToConstant: 60).isActive = true view.addSubview(interesseButton) interesseButton.translatesAutoresizingMaskIntoConstraints = false interesseButton.topAnchor.constraint(equalTo: mijnProfielField.bottomAnchor, constant: 10).isActive = true interesseButton.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 10).isActive = true interesseButton.heightAnchor.constraint(equalToConstant: 30).isActive = true view.addSubview(compButton) compButton.translatesAutoresizingMaskIntoConstraints = false compButton.topAnchor.constraint(equalTo: mijnProfielField.bottomAnchor, constant: 10).isActive = true compButton.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: -10).isActive = true compButton.heightAnchor.constraint(equalToConstant: 30).isActive = true view.addSubview(beoorButton) beoorButton.translatesAutoresizingMaskIntoConstraints = false beoorButton.topAnchor.constraint(equalTo: mijnProfielField.bottomAnchor, constant: 10).isActive = true beoorButton.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10).isActive = true beoorButton.heightAnchor.constraint(equalToConstant: 30).isActive = true view.addSubview(underMember) underMember.translatesAutoresizingMaskIntoConstraints = false underMember.topAnchor.constraint(equalTo: beoorButton.bottomAnchor, constant: 15).isActive = true underMember.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 16).isActive = true underMember.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -16).isActive = true underMember.heightAnchor.constraint(equalToConstant: 2).isActive = true underMember.backgroundColor=grayBanner // Add rounded corners to UIView underMember.layer.cornerRadius=0 // Add border to UIView view.addSubview(memberInfoTable) memberInfoTable.translatesAutoresizingMaskIntoConstraints = false memberInfoTable.topAnchor.constraint(equalTo: underMember.bottomAnchor, constant: 10).isActive = true memberInfoTable.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 16).isActive = true memberInfoTable.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -16).isActive = true memberInfoTable.heightAnchor.constraint(equalToConstant: 340).isActive = true view.addSubview(cell1) cell1.translatesAutoresizingMaskIntoConstraints = false cell1.topAnchor.constraint(equalTo: underMember.bottomAnchor, constant: 10).isActive = true cell1.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 16).isActive = true cell1.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -16).isActive = true cell1.heightAnchor.constraint(equalToConstant: 80).isActive = true view.addSubview(cell2) cell2.translatesAutoresizingMaskIntoConstraints = false cell2.topAnchor.constraint(equalTo: cell1.bottomAnchor, constant: 0).isActive = true cell2.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 16).isActive = true cell2.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -16).isActive = true cell2.heightAnchor.constraint(equalToConstant: 240).isActive = true view.addSubview(profileView) profileView.translatesAutoresizingMaskIntoConstraints = false profileView.topAnchor.constraint(equalTo: underMember.bottomAnchor, constant: 0).isActive = true profileView.centerXAnchor.constraint(equalTo: self.cell2.centerXAnchor).isActive = true profileView.heightAnchor.constraint(equalToConstant: 140).isActive = true profileView.widthAnchor.constraint(equalToConstant: 140).isActive = true view.addSubview(nameField) nameField.translatesAutoresizingMaskIntoConstraints = false nameField.topAnchor.constraint(equalTo: profileView.bottomAnchor, constant: -10).isActive = true nameField.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 24).isActive = true nameField.heightAnchor.constraint(equalToConstant: 50).isActive = true view.addSubview(aboutmeTitle) aboutmeTitle.translatesAutoresizingMaskIntoConstraints = false aboutmeTitle.topAnchor.constraint(equalTo: nameField.bottomAnchor, constant: 10).isActive = true aboutmeTitle.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 24).isActive = true view.addSubview(aboutMeLabel) aboutMeLabel.translatesAutoresizingMaskIntoConstraints = false aboutMeLabel.topAnchor.constraint(equalTo: aboutmeTitle.bottomAnchor, constant: 1).isActive = true aboutMeLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -32).isActive = true aboutMeLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 24).isActive = true view.addSubview(underTable) underTable.translatesAutoresizingMaskIntoConstraints = false underTable.topAnchor.constraint(equalTo: memberInfoTable.bottomAnchor, constant: 10).isActive = true underTable.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 16).isActive = true underTable.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -16).isActive = true underTable.heightAnchor.constraint(equalToConstant: 2).isActive = true underTable.backgroundColor=grayBanner // Add rounded corners to UIView underTable.layer.cornerRadius=0 view.addSubview(todoInfoTable) todoInfoTable.translatesAutoresizingMaskIntoConstraints = false todoInfoTable.topAnchor.constraint(equalTo: underTable.bottomAnchor, constant: 20).isActive = true todoInfoTable.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -16).isActive = true todoInfoTable.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 16).isActive = true view.addSubview(todocell1) todocell1.translatesAutoresizingMaskIntoConstraints = false todocell1.topAnchor.constraint(equalTo: underTable.bottomAnchor, constant: 20).isActive = true todocell1.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -16).isActive = true todocell1.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 16).isActive = true todocell1.heightAnchor.constraint(equalToConstant: 60).isActive = true todocell1.layer.cornerRadius = 12 todocell1.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] view.addSubview(todocell2) todocell2.translatesAutoresizingMaskIntoConstraints = false todocell2.topAnchor.constraint(equalTo: todocell1.bottomAnchor, constant: 0).isActive = true todocell2.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -16).isActive = true todocell2.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 16).isActive = true todocell2.heightAnchor.constraint(equalToConstant: 200).isActive = true view.addSubview(todoTitle) todoTitle.translatesAutoresizingMaskIntoConstraints = false todoTitle.centerYAnchor.constraint(equalTo: self.todocell1.centerYAnchor).isActive = true todoTitle.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 24).isActive = true view.addSubview(addToDo) addToDo.translatesAutoresizingMaskIntoConstraints = false addToDo.centerYAnchor.constraint(equalTo: self.todocell1.centerYAnchor).isActive = true addToDo.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -24).isActive = true } @objc func addtodo(){ let todo = NewToDoController() present(todo, animated: true, completion: nil) } @objc func openInteresses(){ let interesses = InteressesController() present(interesses, animated: true, completion: nil) } @objc func openMenu(){ let menu = MenuController() present(menu, animated: true, completion: nil) } @objc func changeOpenVoor(){ let accessToken: String? = KeychainWrapper.standard.string(forKey: "token") let userId: String? = KeychainWrapper.standard.string(forKey: "id") let request = NSMutableURLRequest(url: NSURL(string: "https://gipaa.nl/app/changeopen_json.php")! as URL) request.httpMethod = "POST" let postString = "userId=\(userId!)&token=\(accessToken!)&change=yes" request.httpBody = postString.data(using: String.Encoding.utf8) let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in // ensure there is no error for this HTTP response guard error == nil else { print ("error: \(error!)") return } // ensure there is data returned from this HTTP response guard let content = data else { print("No data") return } // serialise the data / NSData object into Dictionary [String : Any] guard let json = (try? JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [String: Any] else { print("Not containing JSON") return } let melding = json["melding"] as? String if(melding == "success"){ DispatchQueue.main.async { self.viewDidLoad() self.viewWillAppear(true) } } if(melding == "Error"){ self.displayMessage(userMessage: "Er is een onbekende fout opgetreden.") print("error=\(String(describing: error))") return } } task.resume() } func displayMessage(userMessage:String) -> Void { DispatchQueue.main.async { let alertController = UIAlertController(title: "Alert", message: userMessage, preferredStyle: .alert) let OKAction = UIAlertAction(title: "OK", style: .default) { (action:UIAlertAction!) in // Code in this block will trigger when OK button tapped. print("Ok button tapped") } alertController.addAction(OKAction) self.present(alertController, animated: true, completion:nil) } }
}