ios - 使用 Grand Central Dispatch Swift 3 分配数据

标签 ios swift3 grand-central-dispatch mapbox

我创建了一个用于下载数据的网络文件,我想将数据分配给另一个 View Controller ,这样我就可以用注释填充 map 。数据下载成功,但我无法将其分配给 View Controller 。只有当我在 View Controller 中包含网络代码并使用 DispatchQueue.main.async 时,我才能使其正常工作。我想将网络文件和 View Controller 分开。任何见解将不胜感激。提前对多行代码表示歉意。

网络文件如下:

import UIKit

class Networking {

static let shared = Networking()

var objects = [Any]()

func getData (_ completionHandler:@escaping (Location?) -> ()) {

    //Create the url with NSURL reuqest
    let url = URL(string: "http://localhost:3000/locations")

    let request = NSMutableURLRequest(url: url! as URL)

    //Set HTTP method as GET
    request.httpMethod = "GET"

    //HTTP Headers
    request.addValue("application/json", forHTTPHeaderField: "Accept")

    //Create dataTask using the session object to send data to the server
    URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in

        guard let data = data,
            let dataStore = String(data: data, encoding: String.Encoding.utf8) else {
                print("Could not find network")
                completionHandler(nil)
                return
        }

        guard error == nil else {
            print("Error calling GET")
            completionHandler(nil)
            return
        }

        let HTTPResponse = response as! HTTPURLResponse
        let statusCode = HTTPResponse.statusCode

        if (statusCode == 200) {
            print("Files downloaded successfully. \(dataStore)" )
        } else {
            completionHandler(nil)
            return
        }

        //Create json object from data
        do {

            let json = try! JSONSerialization.jsonObject(with: data , options: []) as? [[String: Any]]
let location: [Location] = []

            if let array = json {

                for i in 0 ..< array.count {

                    if let data_object = array[i] as? [String: Any] {

                        if let _id = data_object["_id"] as? String,
                            let name = data_object["name"] as? String,
                            let imageID = data_object["imageID"] as? String,
                            let category = data_object["category"] as? String,
                            let details = data_object["details"] as? String,
                            let latitude = data_object["latitude"] as? Double,
                            let longitude = data_object["longitude"] as? Double {

                            var dictionary  = [_id, name, imageID, category, details, latitude, longitude] as [Any]

                            dictionary.append(location)

                        }
                    }
                } 
             }  
         }

        }.resume()
    }
}

模型如下:

class Location {

var _id : String
var name : String
var imageID : String
var category : String
var details : String
var latitude : Double
var longitude : Double

init?(_id: String, name: String, imageID: String, category: String, details: String, latitude: Double, longitude: Double) {

    self._id = _id
    self.name = name
    self.imageID = imageID
    self.category = category
    self.details = details
    self.latitude = latitude
    self.longitude = longitude

  }
}

View Controller 如下:

 class MapViewController: UIViewController, MGLMapViewDelegate, UIGestureRecognizerDelegate {

 override func viewDidLoad() {
    super.viewDidLoad()

    mapView.delegate = self


    Networking.shared.getData { (locations) in


    }

    populateMap()

}

func populateMap (){

    let point = MGLPointAnnotation()
    for location in locations {
        let coordinate = CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude )
        point.coordinate = coordinate
        point.title = location.name
        point.subtitle = location.category
        self.mapView.addAnnotation(point)

    }
}

最佳答案

您仅在失败情况下执行完成 block 。一旦成功解析数据并将数组作为参数传递给closure/block,就执行完成 block 。

import UIKit

class Networking {

static let shared = Networking()

var objects = [Any]()

func getData (_ completionHandler:@escaping ([Location]?) -> ()) {

    //Create the url with NSURL reuqest
    let url = URL(string: "http://localhost:3000/locations")

    let request = NSMutableURLRequest(url: url! as URL)

    //Set HTTP method as GET
    request.httpMethod = "GET"

    //HTTP Headers
    request.addValue("application/json", forHTTPHeaderField: "Accept")

    //Create dataTask using the session object to send data to the server
    URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in

        guard let data = data,
            let dataStore = String(data: data, encoding: String.Encoding.utf8) else {
                print("Could not find network")
                completionHandler(nil)
                return
        }

        guard error == nil else {
            print("Error calling GET")
            completionHandler(nil)
            return
        }

        let HTTPResponse = response as! HTTPURLResponse
        let statusCode = HTTPResponse.statusCode

        if (statusCode == 200) {
            print("Files downloaded successfully. \(dataStore)" )
        } else {
            completionHandler(nil)
            return
        }

        //Create json object from data
        do {

            let json = try! JSONSerialization.jsonObject(with: data , options: []) as? [[String: Any]]
let location: [Location] = []

            if let array = json {

                for i in 0 ..< array.count {

                    if let data_object = array[i] as? [String: Any] {

                        if let _id = data_object["_id"] as? String,
                            let name = data_object["name"] as? String,
                            let imageID = data_object["imageID"] as? String,
                            let category = data_object["category"] as? String,
                            let details = data_object["details"] as? String,
                            let latitude = data_object["latitude"] as? Double,
                            let longitude = data_object["longitude"] as? Double {

                            var dictionary  = [_id, name, imageID, category, details, latitude, longitude] as [Any]

                            dictionary.append(location) //am not sure of what this means test your code

                            completionHandler(location)
                        }
                    }
                } 
             }  
         }

        }.resume()
    }
}

代码中还有一些错误:

  1. 您的完成 block 需要 Location 作为参数。但在您的代码中您正在创建一个位置数组。

    让位置:[位置] = []

所以我修改了完成 block 参数以返回位置数组

  1. 在您正在创建的 for 循环中

    var dictionary = [_id, name, imageID, category, details, latitude, longitude] as [Any]

并将其附加到 dictionary.append(location) 我不知道这段代码是什么。我相信你实际上想做的是从数据创建一个位置对象,然后将它添加到位置数组

location.append(your_new_location_object)

希望对你有帮助

关于ios - 使用 Grand Central Dispatch Swift 3 分配数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45973657/

相关文章:

ios - 为什么DispatchGroup会干扰主队列?

iphone - 更改 UITableViewCell 附件后 UITableViewCellAccessoryDe​​tailDisclosureButton 消失

ios - 任何超过 255 秒的任务都会导致 GCD 崩溃

android - OpenGL ES 2.0 : Unable to perform simple rotation

ios - 我想移动指定自动布局的 View 的位置。 (ios 6,xcode 4.5)

ios - 在 swift 3 中将字节数组转换为 PDF

ios - Swift:与 DispatchGroup 的死锁

swift - 嵌套通知中的 DispatchGroup [weak self] 处理

date - NSDate 从 Swift 2.3 到 Date 从 Swift 3 转换

ios - 在弹出 segue 为 'dismissed' 后刷新父 View 上的 IBOutlet 外观