简体   繁体   English

iOS Swift:函数未返回正确值

[英]iOS Swift: function not returning correct value

I am developing an app in Swift for my high school sports teams. 我正在为我的中学运动队开发Swift应用程序。 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: 这是我的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. 单击按钮后,它会锁定到tabBarController,并将AppDelegate的团队变量设置为选定的团队。 In the AppDelegate, I created a function which retrieves the link of a video from parse.com based upon the team variable. 在AppDelegate中,我创建了一个函数,该函数根据team变量从parse.com检索视频的链接。 I then put this function, which is supposed to return the embedLink, in my html code for my web view. 然后,我将这个函数(应该返回embedLink)放在Web视图的html代码中。 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: 我在函数中添加了打印语句,这似乎表明我在从解析运行查询之前返回了embedLink变量,这似乎是我的问题:

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. 因为您正在使用异步操作来查找链接,所以函数将后台任务完成并找到链接之前返回: self.embedLink在函数返回时未设置。

You need to pass a completion handler as an argument, and call that once the background task completes (passing the embedLink you just found): 您需要将完成处理程序作为参数传递,并在后台任务完成后调用它(传递刚刚找到的embedLink):

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); 因此,函数getLink()本身不会返回值(它不能等待在后台运行的任务); 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. 我认为query.findObjectsInBackgroundWithBlock{是异步的,因此当请求未完成时返回embedLink时可能为nil。 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 同样要确保在请求完成后,其他任何按钮/动作都可以激活,可能是必需的进度条,例如MBProgressHUD

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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