简体   繁体   中英

iOS Swift: function not returning correct value

I am developing an app in Swift for my high school sports teams. It gets the variable of what team you want to view when you click the button on the home view controller, and gets a link to a certain video based on the team selected. The problem occurs when I first select the team; it shows nothing, but when I click home and then the team again, it shows.

This is my code for the buttons in HomeViewController:

import UIKit

class homeViewController: UIViewController {

@IBAction func varsityBasketballBtn(sender: AnyObject) {
    appDelegate.team = "VARSITY BASKETBALL"
}

@IBAction func varsityHockeyBtn(sender: AnyObject) {
    appDelegate.team = "VARSITY HOCKEY"
}

@IBAction func jvBasketballBtn(sender: AnyObject) {
    appDelegate.team = "JV BASKETBALL"
}

@IBAction func jvHockeyBtn(sender: AnyObject) {
    appDelegate.team = "JV HOCKEY"
}

After you click a button, it segues to the tabBarController, and sets the team variable of the AppDelegate to the team selected. In the AppDelegate, I created a function which retrieves the link of a video from parse.com based upon the team variable. I then put this function, which is supposed to return the embedLink, in my html code for my web view. when I first load the app and choose a team, the web view is blank, but after going home and re-selecting the team, it shows the correct video. I added print statements into my function which seem to show me that it is returning the embedLink variable before it runs my query from parse which seems to be my issue:

var embedLink:String = ""

func getLink() -> String{

    let query = PFQuery(className:"LiveLink")
    print("This is right after query")
    query.findObjectsInBackgroundWithBlock{
        (liveLink:[PFObject]?,error: NSError?) -> Void in
        print("This is before livelink")

        if error == nil && liveLink != nil {
            for link in liveLink!{
                if link["team"] as! String == self.team{
                    self.embedLink = link["link"] as! String
                    print("This is link in query: \(self.embedLink)")
                }
            }
        } else {
            print(error)
        }
    }
    print("This is link in func: \(embedLink)")
    return embedLink
}

Please advise as to how you think this could be done correctly. Any help is appreciated.

Because you are using an asynchronous operation to find the link, your function returns before the background task completes and the link is found: self.embedLink is not set by the time your function returns.

You need to pass a completion handler as an argument, and call that once the background task completes (passing the embedLink you just found):

func getLink(withCompletion completion:((link:String)-> (Void))) {

    let query = PFQuery(className:"LiveLink")
    print("This is right after query")
    query.findObjectsInBackgroundWithBlock{
        (liveLink:[PFObject]?,error: NSError?) -> Void in
        print("This is before livelink")

        if error == nil && liveLink != nil {
            for link in liveLink!{
                if link["team"] as! String == self.team{

                    let embedLink = link["link"] as! String

                    // Call completion handler,
                    // passing the found link:                        
                    completion(link: embedLink)
                }
            }
        } 
        else {
            print(error)
        }
    }
}

So, the function getLink() itself does not return a value (it can't wait fir a task that runs in the background); instead it takes a "callback" block to call when the background task completes.

I think query.findObjectsInBackgroundWithBlock{ is async so embedLink might be nil when it is returned when the request wasn't finished. So try to use closure

    func getLink(completion:(String?)->Void){
       if link["team"] as! String == self.team {
          self.embedLink = link["link"] as! String
          print("This is link in query: \(self.embedLink)")
          completion(self.embedLink)
       }
    }

   getLink { (link) -> Void in
      ...
      print(link!)
      ...
   }

Also to make sure after the request done then any other button/actions can be active, may be a progress bar is necessary like MBProgressHUD

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM