【问题标题】:How to block anything from happening until a func has been completed?在函数完成之前如何阻止任何事情发生?
【发布时间】:2018-06-01 15:22:20
【问题描述】:

我一直在环顾四周,但没有找到防止任何事情发生的方法,直到某个功能完成。基本上,函数下方的事件发生在函数之前。让我向您展示代码和控制台输出。

代码:

if locationSwitch.isOn == true {
            let url = "https://maps.googleapis.com/maps/api/geocode/json?latlng=\(location.latitude),\(location.longitude)&result_type=locality&key=AIzaSyDI-ZacHyPbLchRhkoaUTDokwj--z_a_jk"
            loadUrl(url: url) { optionalLocation in
                guard let nonOptionalLocation = optionalLocation else {
                    // Location was nil; Handle error case here
                    return
                }
                // Do something with your location here, like setting UI or something
                print("Optional Location: \(optionalLocation)")
                print("nonOptional Location: \(nonOptionalLocation)")
                cityState = nonOptionalLocation
                print("cityState: \(cityState)")
                print("Within Func")
            }
            print("Within If")
        } else {
            lat = 0.0
            lng = 0.0
            cityState = ""
        }
        print("After If")
        print("cityState Outside If Statement: \(cityState)")
        CoreDataHandler.savePhotoObject(locationCoordinateLatitude: lat, locationCoordinateLongitude: lng, locationLocality: cityState, dateCreated: date, discription: discriptionBox.text!, photo: selectedImageData!)
    }

控制台输出:

Before If
Within If
After If
cityState Outside If Statement:
Optional Location: Optional("San Francisco, CA, USA")
nonOptional Location: San Francisco, CA, USA
cityState: San Francisco, CA, USA
Within Func

如你所见

Optional Location: Optional("San Francisco, CA, USA")
nonOptional Location: San Francisco, CA, USA
cityState: San Francisco, CA, USA
Within Func

应该在之前

Within If

我相信这是因为 loadUrl 函数需要很长时间才能完成,以至于代码越过它并完成它下面的代码,然后 loadUrl 完成,然后在其他所有内容之后打印。这不会是一个问题,除了设置等于nonOptionalLocation 的变量在loadUrl 函数完成后被调用,因为loadUrl 在代码的其余部分结束后完成了应该等于的变量nonOptionalLocation 实际上等于""

现在有人知道如何完成这项工作吗?我认为我需要在loadUrl 完成之前阻止任何事情的发生,但如果您知道另一种方法,请分享。谢谢你。

【问题讨论】:

  • @PatrickHaertel 绝对相关。
  • @vadian 和马特请原谅我的最后评论。我同意你的观点,这是相关的。多亏了 vadian,我才在我的代码中解决了这个问题之后才浏览了这篇文章,而且我一定是快速浏览了这篇文章,因为我显然没有抓住重点。请原谅我。

标签: ios swift function


【解决方案1】:

loadUrl异步工作,只需将返回数据后要执行的代码放入完成块

if locationSwitch.isOn == true {
    loadUrl(url: url) { optionalLocation in
        guard let nonOptionalLocation = optionalLocation else {
            // Location was nil; Handle error case here
            return
        }
        // Do something with your location here, like setting UI or something
        print("Optional Location: \(optionalLocation)")
        print("nonOptional Location: \(nonOptionalLocation)")
        cityState = nonOptionalLocation
        print("cityState: \(cityState)")
        print("Within Func")
        DispatchQueue.main.async {
            CoreDataHandler.savePhotoObject(locationCoordinateLatitude: lat, locationCoordinateLongitude: lng, locationLocality: cityState, dateCreated: date, discription: discriptionBox.text!, photo: selectedImageData!)
        }
    }
} else {
    CoreDataHandler.savePhotoObject(locationCoordinateLatitude: 0.0, locationCoordinateLongitude: 0.0, locationLocality: "", dateCreated: date, discription: discriptionBox.text!, photo: selectedImageData!)
}

【讨论】:

  • 这无法完成,因为我收到此错误:UITextField.text must be used only from main thread
  • vadian 的回答是正确的。你根本不了解异步完成处理程序是如何工作的。完成处理程序的重点是,如果在后台线程上调用该完成处理程序,那么您应该将要在 URL 加载后运行的代码放在完成处理程序内(在花括号内..),那么您需要包装在调用DispatchQueue.main.async() 时调用 UIKit 函数的任何代码(如 vadian 的回答所示)
  • 我也必须把它放在 else 语句中,对吗?
  • 不,你必须写两次CoreDataHandler.savePhotoObject( 行。我再次更新了答案。但是你真的要保存一个准空的照片对象吗?
  • @vadian 是的。我需要将其保存为空,因为当按下继续按钮时会加载另一个视图,其中加载了所有这些数据,例如,如果 cityState == "" 则隐藏标签;但是,如果 cityState != "" 没有隐藏标签。我现在遇到的一个以前没有的问题是,当按下继续按钮时,下一页上加载的数据是前一次的数据。要获得正确的数据,您必须按继续,然后按返回(关闭当前视图控制器),然后再次按继续。我该如何解决这个问题?
【解决方案2】:

您是否使用过 DispatchQueue.main.sync{},它可能会在您的 UI 中停留一段时间,这并不好,但如果您对此没有任何问题,那么您可以尝试一下。

if locationSwitch.isOn{

        DispatchQueue.main.sync {

            let url = "https://maps.googleapis.com/maps/api/geocode/json?latlng=\(location.latitude),(location.longitude)&result_type=locality&key=AIzaSyDI-ZacHyPbLchRhkoaUTDokwj--z_a_jk"

            loadUrl(url: url) { optionalLocation in
                guard let nonOptionalLocation = optionalLocation else {
                    return
                }

                print("Optional Location: \(optionalLocation)")
                print("nonOptional Location: \(nonOptionalLocation)")
                cityState = nonOptionalLocation
                print("cityState: \(cityState)")
                print("Within Func")
            }
        }
        print("Within If")
    } else {
        lat = 0.0
        lng = 0.0
        cityState = ""
    }
    print("After If")
    print("cityState Outside If Statement: \(cityState)")
    CoreDataHandler.savePhotoObject(locationCoordinateLatitude: lat, locationCoordinateLongitude: lng, locationLocality: cityState, dateCreated: date, discription: discriptionBox.text!, photo: selectedImageData!)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多