如何在执行函数之前等待 Swift 中的变量? (迅速)

Posted

技术标签:

【中文标题】如何在执行函数之前等待 Swift 中的变量? (迅速)【英文标题】:How to wait for variable in Swift before executing function? (Swift) 【发布时间】:2018-06-24 18:38:12 【问题描述】:

下面是我的代码。我想要我的 Poststring 中的纬度和经度值。但是当他执行后字符串时,我的值仍然为零,因为 swift 还没有更新位置。那么如何在 poststring 获取值之前等待纬度和经度呢?我听说过一些 didset 但我不知道如何使用它以及我必须在哪里使用它。

import Foundation
import CoreLocation


protocol FeedmodelProtocol: class 
    func itemsDownloaded(items: NSArray)



class Feedmodel: NSObject, URLSessionDataDelegate, CLLocationManagerDelegate 



    weak var delegate: FeedmodelProtocol!
    let locationManager = CLLocationManager() // create Location Manager object
    var latitude : Double?
    var longitude : Double?

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 
        guard let location: CLLocationCoordinate2D = manager.location?.coordinate else  return 
        // set the value of lat and long
        latitude = location.latitude
        longitude = location.longitude

    

    func downloadItems() 
        self.locationManager.requestAlwaysAuthorization()

        // For use in foreground
        // You will need to update your .plist file to request the authorization
        self.locationManager.requestWhenInUseAuthorization()

        if CLLocationManager.locationServicesEnabled() 
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters

            locationManager.startUpdatingLocation()

        
        let myUrl = URL(string: "http://example.com/stock_service4.php");
        let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)
        var request = URLRequest(url:myUrl!)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        var postString = ""
        if let lat = latitude, let long = longitude 
            locationManager.stopUpdatingLocation()
            postString = "lati=\(Int(lat))&longi=\(Int(long))"
            // do task here now that postString is not empty
        
        request.httpBody = postString.data(using: .utf8)
        let task = defaultSession.dataTask(with: request)  data, response, error in


            guard let data = data, error == nil else                                                  // check for fundamental networking error
                print("error=\(String(describing: error))")
                return

            


            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200            // check for http errors
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(String(describing: response))")
                print("error=\(String(describing: error))")
            

            let responseString = String(data: data, encoding: .utf8)
            print("responseString = \(String(describing: responseString))")
            print("error=\(String(describing: error))")
            self.parseJSON(data)

        

        task.resume()

    

    func parseJSON(_ data:Data) 

        var jsonResult = NSArray()

        do
            jsonResult = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray;
         catch let error as NSError 
            print(error)

        

        var jsonElement = NSDictionary()
        let stocks = NSMutableArray()

        for i in 0 ..< jsonResult.count
        
            print(jsonResult)
            jsonElement = jsonResult[i] as! NSDictionary


            let stock = Stockmodel()

            //the following insures none of the JsonElement values are nil through optional binding
            if  let Datum = jsonElement["Datum"] as? String,
                let Tankstelle = jsonElement["Tankstelle"] as? String,
                let Kraftstoff1 = jsonElement["Kraftstoff1"] as? String,
                let Preis1 = jsonElement["Preis1"] as? String,
                let Kraftstoff2 = jsonElement["Kraftstoff2"] as? String,
                let Preis2 = jsonElement["Preis2"] as? String,
                let Notiz = jsonElement["Notiz"] as? String,
                let longitude = jsonElement["longitude"] as? String,
                let latitude = jsonElement["latitude"] as? String



            
                print (Datum)
                print(Tankstelle)
                print(Kraftstoff1)
                print(Preis1)
                print(Kraftstoff2)
                print(Preis2)
                print(Notiz)
                print(longitude)
                print(latitude)
                stock.Datum = Datum
                stock.Tankstelle = Tankstelle
                stock.Kraftstoff1 = Kraftstoff1
                stock.Preis1 = Preis1
                stock.Kraftstoff2 = Kraftstoff2
                stock.Preis2 = Preis2
                stock.Notiz = Notiz
                stock.longitude = longitude
                stock.latitude = latitude


            

            stocks.add(stock)

        

        DispatchQueue.main.async(execute:  () -> Void in

            self.delegate.itemsDownloaded(items: stocks)

        )
    

谢谢!

【问题讨论】:

【参考方案1】:

每次更新位置时都会调用函数locationManager(_:didUpdateLocations:)。所以你应该像这样在位置管理器中添加downloadItems()

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 
    guard let location: CLLocationCoordinate2D = manager.location?.coordinate else  return 

    // set the value of lat and long

    latitude = location.latitude
    longitude = location.longitude

    downloadItems()

查看有关locationManager(_:didUpdateLocations:)的文档

【讨论】:

@JohnsonSteinberg 我很高兴听到这个消息!您可以接受此回复,这样所有用户都可以看到对您有用的内容Learn more about accepted answer。

以上是关于如何在执行函数之前等待 Swift 中的变量? (迅速)的主要内容,如果未能解决你的问题,请参考以下文章

在执行代码之前等待 Swift 动画完成

如何让类中的初始化方法等待 Firestore 在 Swift 4 中完成?

如何等待异步函数 Swift

我必须等待 Swift 中的 didReadRSSI() 函数吗?

在返回函数的变量之前,如何等待 promise 完成?

在执行代码之前等待用户关闭模态视图(Swift 2.0)