0

I use a design pattern MVC. I have model and controller. Model must get data from the database and send it to controller. I have such structure, for example, but it does not work:

Class of model

    class AuthModel
{

    func getDataFrom(request: NSMutableURLRequest, completion: (result: NSDictionary)->())
    {
        let session = NSURLSession.sharedSession()

        let task = session.dataTaskWithRequest(request) { (data, response, error) in

            if let data = data
            {
                let result = try! NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) as! NSDictionary

                completion(result: result)
            } else {
                print(error?.localizedDescription)
            }
        }

        task.resume()
    }



    func getUser(let username : String, let password : String) -> NSDictionary
    {
        let request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8888/together/auth.php")!)
        request.HTTPMethod = "POST"

        let postString = "user=\(username)&pass=\(password)"
        request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)

        var values : NSDictionary = ["":""]

        getDataFrom(request) { (result) in
            values = result
            print(values["username"]) //output1
        }

        print(values["username"]) // output2


        return values

    }
}

Part of controller

@IBAction func LoginBtn(sender: AnyObject)
{
let values = authModel.getUser(usernameField.text!, password: passwordField.text!) as NSDictionary

}

Output1 shows me the value that I want, but output2 equals nil. Why? I guess it because of session and task. So maybe it does not want to return value? How should I change the code? I tried to cancel the task instead of resume it, but it led to the error.

Roman Shirokov
  • 329
  • 4
  • 12
  • 1
    I think the post I've linked answers your questions. If you discover later that this is not the case, you can comment here about a specific issue. – Eric Aya Mar 15 '16 at 16:42
  • Well, maybe, but I still cannot solve the problem. Look at apiManager (the link you gave me). I see that I can assign variable inside the callback and use it there (for example, to print it up), but if I try to assign the variable which is outside of callback by this data - it disappears. So, it is not possible? If I want to save the data and use it later, but not in the callback? – Roman Shirokov Mar 15 '16 at 17:05
  • P.S. I rewrote the model. Look at it, please. – Roman Shirokov Mar 15 '16 at 17:12
  • This is still similar issues to me: *you can't return data from an asynchronous task*, you have to use callbacks. Here are other examples of this mechanism: http://stackoverflow.com/a/35832296/2227743, http://stackoverflow.com/a/35720670/2227743, http://stackoverflow.com/a/35702383/2227743 Don't worry, if you still can't resolve your issue, this question can be reopened (but I'd prefer avoid that since the questions are really similar). – Eric Aya Mar 15 '16 at 17:25
  • BTW, your `output2` is *outside* the callback, so yes indeed it is not populated - it should be in the same scope as the other one. Forget about using `return` entirely... use a callback for getUser too. – Eric Aya Mar 15 '16 at 17:32
  • Okay, thank you. However, it seems to me very weird. I wanted to get JSON from URL and keep it as a dictionary, because it much easier to get necessary data when you need it. Using of callback is a bit inconveniently, IMHO. Am I wrong? For example, I want to login. When I sign in, server (URL) gives me info about the user. I want to keep it and use it later. – Roman Shirokov Mar 15 '16 at 18:06
  • It certainly can be seen as [inconvenient](http://callbackhell.com/), but this is the preferred way for this kind of task. If you really don't like callbacks, you can try queuing NSOperations (but IMO it's not easier to master at all), using delegates (a whole topic of itself), NSNotifications (clunky, don't), and many other ways... But for *this*, in Swift, I really suggest learning "completion handlers". :) – Eric Aya Mar 15 '16 at 18:10

0 Answers0