我创建了一个用于下载数据的网络文件,我想将数据分配给另一个 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()
}
}
代码中还有一些错误:
您的完成 block 需要 Location 作为参数。但在您的代码中您正在创建一个位置数组。
让位置:[位置] = []
所以我修改了完成 block 参数以返回位置数组
在您正在创建的 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/