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 UIKit
extension 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)
}
}
}