1

i have a problem when parsing json code from the database into the iphone uilabel. the page seem to load faster the the json data could be downloaded. every time i run it, it always leave an empty UIlabel but it did show on print. how do i make it so that the page will wait for the json to be downloaded and then it could continue in showing the page with the json content in it.

the page, i am using uiview that are placed inside viewcontroller

class ContentView: UIView {


    let request = requestQuestion()
    var currentVC:ViewController?
    var times = "10"
    let time = UILabel()
    let textViews = UILabel()
    let recommendList = recommend()
    let choices = ChoicesCollections()
    var content = ""

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setupView(){
        content = request.getquestion(questions: "212", url: "http://localhost/memory/question.php")
        print(content)
        time.translatesAutoresizingMaskIntoConstraints = false
        textViews.translatesAutoresizingMaskIntoConstraints = false
        recommendList.translatesAutoresizingMaskIntoConstraints = false
        choices.translatesAutoresizingMaskIntoConstraints = false

        addSubview(time)
        addSubview(textViews)
        addSubview(recommendList)
        addSubview(choices)

        time.text = times
        time.font = UIFont.boldSystemFont(ofSize: 20)
        time.textAlignment = .center
        time.topAnchor.constraint(equalTo: topAnchor, constant: 40).isActive = true
        time.centerXAnchor.constraint(equalTo: centerXAnchor, constant: 0).isActive = true
        time.widthAnchor.constraint(equalToConstant: 50).isActive = true
        time.heightAnchor.constraint(equalToConstant: 25).isActive = true

        textViews.numberOfLines = 7
        textViews.font = UIFont.boldSystemFont(ofSize: 30)
        textViews.text = content
        textViews.textAlignment = .center
        textViews.topAnchor.constraint(equalTo: topAnchor, constant: 0).isActive = true
        textViews.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        textViews.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
        textViews.bottomAnchor.constraint(equalTo: centerYAnchor, constant: 100).isActive = true

        choices.topAnchor.constraint(equalTo: textViews.bottomAnchor, constant: 60).isActive = true
        choices.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        choices.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
        choices.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true

        recommendList.backgroundColor = .black
        recommendList.bottomAnchor.constraint(equalTo: choices.topAnchor,constant: -5).isActive = true
        recommendList.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        recommendList.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
        recommendList.heightAnchor.constraint(equalToConstant: 50).isActive = true
    }
}

the json page

struct question:Decodable {
        let question:String
        let boxA:String
        let boxB:String
        let boxC:String
        let boxD:String
        let categories:String
    }
func getquestion(questions:String,url:String)->String{
        //return "which state that are bordering mexico?"
        let request = NSMutableURLRequest(url: NSURL(string: url)! as URL)
        request.httpMethod = "POST"
        let postString = "question=\(questions)"
        request.httpBody = postString.data(using: .utf8)
        var returns = ""
        let task = URLSession.shared.dataTask(with: request as URLRequest) {
            data, response, error in
            if error != nil {
                print("error=\(String(describing: error))")
                return
            }
            // read the response from php
            do {
                let decoder = JSONDecoder()
                let product = try decoder.decode(question.self, from: data!)
                DispatchQueue.main.async{
                    returns = product.question
                }

            } catch let error as NSError {
                print(error)
            }
        }
        task.resume()
        return returns
    }
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87

1 Answers1

1

You need a completion

func getquestion(questions:String,url:String,completion:@escaping((_ str:String?)->())){
  //return "which state that are bordering mexico?"
  var request = URLRequest(url: URL(string: url)!)
  request.httpMethod = "POST"
  let postString = "question=\(questions)"
  request.httpBody = postString.data(using: .utf8)
  var returns = ""
  let task = URLSession.shared.dataTask(with: request as URLRequest) {
    data, response, error in
    if error != nil {
      print("error=\(String(describing: error))")
      completion(nil)
      return
    }
    // read the response from php
    do {
      let decoder = JSONDecoder()
     // let product = try decoder.decode(question.self, from: data!)
      DispatchQueue.main.async{
        completion(product.question)
      }

    } catch  {
      print(error)
      completion(nil)
    }
  }
  task.resume()

}

content = request.getquestion(questions: "212", url: "http://localhost/memory/question.php")
   { (str) in
  print(str)
}
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • how do i call it in the contentView? – user2957119 Nov 25 '18 at 10:42
  • 1
    thank you so much it worked, this is the correct answer, but a little modification at the end. should be like this. request.getquestion(questions: "212", url: "http://localhost/memory/question.php", completion: { (str) in //print("new \(str)") self.textViews.text = str }) – user2957119 Nov 25 '18 at 10:49