调用urlsession数据后重新加载映射 [英] reload map after calling urlsession data

查看:71
本文介绍了调用urlsession数据后重新加载映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新手,我用静态数据实现了MapKit,并且效果很好,我在调用了后端引脚数据后调用了它,并在操场上表明它可以正常工作,但是地图未显示标记,似乎mapKit没有在正确的时间捕获pins数据,因此我使用Dispatch.Que刷新了地图,但没有刷新,并且没有标记显示.

I am new in swift , I implemented a MapKit with static data , and it worked fine , and I called after that backend pins data and it showed in the playground that it works fine , but the map is not displaying the markers , it seems that the mapKit do not capture the pins data in the right time , so I used Dispatch.Que to refresh the map but I did not refresh and it is displaying without the markers

这是我尝试过的:

import UIKit
import MapKit


class myMapViewController: UIViewController, MKMapViewDelegate {
   
    
    var shops = [Shops]()
    var communities = [Community]()
    var cyclists = [Cyclist]()
    var circuits = [Circuit]()
    var BR = BaseUrl.baseUrl
    
    
    @IBOutlet weak var myMap: MKMapView!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.getShops()
        self.getCircuits()
        self.getCyclists()
        self.getCommunities()
        
        //shops.append(Shops(id: 0, title: "Shop1", latitude: 36.553015 , longitude: 10.592774))
        //shops.append(Shops(id: 0, title: "Shop2", latitude: 35.499414 , longitude: 10.824846))
        //communities.append(Community(id: 0, title: "community1", latitude: 37.276943 , longitude: 10.934709 ))
        //communities.append(Community(id: 0, title: "community2", latitude: 35.427828 , longitude: 9.748186 ))
        //circuits.append(Circuit(id: 0, title: "circuit1", latitude: 33.773035 , longitude: 10.857805 ))
        //cyclists.append(Cyclist(id: 0, title: "cyclist1", latitude: 35.785118 , longitude: 10.000871 ))
        createShopsAnnotations(locations: shops)
        createCircuitsAnnotations(locations: circuits)
        createCommunityAnnotations(locations: communities)
        createCyclistsAnnotations(locations: cyclists)
        
    }
    

    
    
    func createShopsAnnotations(locations:[Shops]){
        
        for location in locations {
            let annotations = MKPointAnnotation()
            annotations.title = location.title as? String
            annotations.coordinate = CLLocationCoordinate2D(latitude: location.latitude as! CLLocationDegrees , longitude: location.longitude as! CLLocationDegrees)
            DispatchQueue.main.async {
                self.myMap.addAnnotation(annotations)
            }
            
        }}
        
        
        func createCircuitsAnnotations(locations:[Circuit]){
            
            for location in locations {
                let annotations = MKPointAnnotation()
                annotations.title = location.title as? String
                annotations.coordinate = CLLocationCoordinate2D(latitude: location.latitude as! CLLocationDegrees , longitude: location.longitude as! CLLocationDegrees)
                DispatchQueue.main.async {
                    self.myMap.addAnnotation(annotations)
                }
            }
            
    }

    

    func createCommunityAnnotations(locations:[Community]){
        
        for location in locations {
            
            let annotations = MKPointAnnotation()
            annotations.title = location.title as? String
            annotations.coordinate = CLLocationCoordinate2D(latitude: location.latitude as! CLLocationDegrees , longitude: location.longitude as! CLLocationDegrees)
            DispatchQueue.main.async {
                self.myMap.addAnnotation(annotations)
            }
            
            
        }}
    
    
    
    func createCyclistsAnnotations(locations:[Cyclist]){
        
        for location in locations {
            
            let annotations = MKPointAnnotation()
            annotations.title = location.title as? String
            annotations.coordinate = CLLocationCoordinate2D(latitude: location.latitude as! CLLocationDegrees , longitude: location.longitude as! CLLocationDegrees)
            
            DispatchQueue.main.async {
                self.myMap.addAnnotation(annotations)
            }
            
        }}
    
    
    func getShops(){
    
        //get
      
       guard let url = URL(string: BR+"/shops") else {
       return
       }
       let session = URLSession.shared
       session.dataTask(with: url)  { ( data , response ,error) in
           if let response = response {
               print(response)
           }
           
           if let data = data {
               print(data)
               do
               {
                   let json = try JSONSerialization.jsonObject(with: data, options: [])as! [[String:Any]]
                self.shops.removeAll()
                
                for item in json {
                    let id = item["shop_id"] as! Int
                    let title = item["title"] as! String
                    let latitude = item["latitude"] as! Double
                    let longitude = item["longitude"] as! Double
                    self.shops.append(Shops(id: id, title: title, latitude: latitude , longitude: longitude))
                }
                
                for item in self.shops {
                    print(item.shop_id)
                    print(item.title)
                    print(item.latitude)
                    print(item.longitude)
                }
                  
               }catch{
                   print(error)
               }
           }
           
       }.resume()
        
            
        }
    
    
    
    
    func getCommunities(){
    
        //get
      
       guard let url = URL(string: BR+"/communities") else {
       return
       }
       let session = URLSession.shared
       session.dataTask(with: url)  { ( data , response ,error) in
           if let response = response {
               print(response)
           }
           
           if let data = data {
               print(data)
               do
               {
                   let json = try JSONSerialization.jsonObject(with: data, options: [])as! [[String:Any]]
                self.communities.removeAll()
                
                for item in json {
                    let id = item["community_id"] as! Int
                    let title = item["title"] as! String
                    let latitude = item["latitude"] as! Double
                    let longitude = item["longitude"] as! Double
                    self.communities.append(Community(id: id, title: title, latitude: latitude , longitude: longitude))
                }
                
                for item in self.communities {
                    print(item.community_id)
                    print(item.title)
                    print(item.latitude)
                    print(item.longitude)
                }
                  
               }catch{
                   print(error)
               }
           }
           
       }.resume()
        
            
        }
  
    
    
    
    func getCircuits(){
    
        //get
      
       guard let url = URL(string: BR+"/circuits") else {
       return
       }
       let session = URLSession.shared
       session.dataTask(with: url)  { ( data , response ,error) in
           if let response = response {
               print(response)
           }
           
           if let data = data {
               print(data)
               do
               {
                   let json = try JSONSerialization.jsonObject(with: data, options: [])as! [[String:Any]]
                self.shops.removeAll()
                
                for item in json {
                    let id = item["circuit_id"] as! Int
                    let title = item["title"] as! String
                    let latitude = item["latitude"] as! Double
                    let longitude = item["longitude"] as! Double
                    self.circuits.append(Circuit(id: id, title: title, latitude: latitude , longitude: longitude))
                }
                
                for item in self.circuits {
                    print(item.circuit_id)
                    print(item.title)
                    print(item.latitude)
                    print(item.longitude)
                }
                  
               }catch{
                   print(error)
               }
           }
           
       }.resume()
        
            
        }
    
    
    func getCyclists(){
    
        //get
      
       guard let url = URL(string: BR+"/cyclists") else {
       return
       }
       let session = URLSession.shared
       session.dataTask(with: url)  { ( data , response ,error) in
           if let response = response {
               print(response)
           }
           
           if let data = data {
               print(data)
               do
               {
                   let json = try JSONSerialization.jsonObject(with: data, options: [])as! [[String:Any]]
                self.cyclists.removeAll()
                
                for item in json {
                    let id = item["cyclist_id"] as! Int
                    let title = item["title"] as! String
                    let latitude = item["latitude"] as! Double
                    let longitude = item["longitude"] as! Double
                    self.cyclists.append(Cyclist(id: id, title: title, latitude: latitude , longitude: longitude))
                }
                
                for item in self.cyclists {
                    print(item.cyclist_id)
                    print(item.title)
                    print(item.latitude)
                    print(item.longitude)
                }
                  
               }catch{
                   print(error)
               }
           }
           
       }.resume()
        
            
        }
    
    
    
    
    
    
    
}

我要做的是使mapkit在正确的时间捕获针脚数据并刷新它的数据,我认为这是正确显示针脚的唯一方法

What I am trying to do is to make the mapkit capture the pins data in the right time and refresh it's data, I think it is the only way to display my pins correctly

推荐答案

获取数据是一项异步任务.在问题中,您正在网络请求结束之前更新数据.将此问题与此版本将MapKit引脚设置为不同的颜色和Rob的答案,您可以将每个URL路径分配给该地点类型:

Getting the data is an async task. In the question you are updating the data before the network request has ended. Combining this question with this one Set MapKit pins with different colors and the answer by Rob you could assign each URL path to the place type:

enum PlaceType {
    case shop, community, cyclist, circuit
    var urlPath: String {
        switch self { 
        case .shop: return "/shops"
        case .community: return "/communities"
        case .circuit: return "/circuits"
        case .cyclist: return "/cyclists"
    }
}

然后您可以在 for 循环中为每个地点类型获取数据.每次调用该方法来获取数据时,您都将传递一个回调,以将返回的位置添加到地图中:

and then you could fetch the data in a for loop for each place type. Each time you call the method to fetch data, you'd pass a callback to add the returned places to the map:

@IBOutlet weak var myMap: MKMapView!

override func viewDidLoad() {
    super.viewDidLoad()
        
    for placeType in PlaceType.allCases {
    // Call each get method with a callback
        fetchData(
            for: placeType,
            completion: { [weak self] places in
                guard let self = self else { return }
                self.myMap.addAnnotations(places)                       
            }
        )
    }        
}

fetchData 方法仅启动网络请求并在完成后调用完成方法:

The fetchData method just starts the network request and calls the completion method when done:

func fetchData(for placeType: PlaceType, completion: @escaping ([Place]) -> Void) {
    guard let url = URL(string: BR + placeType.urlPath) else { return }
    URLSession.shared.dataTask(with: url)  { ( data , response, error) in
        guard let data = data else { return }
        do {
            let places = try JSONDecoder().decode([Place].self, from: data)
            completion(places) // this is the callback!
        } catch {}
    }.resume()
}

Place 类与Rob的答案中的类相同,但是具有解码和编码逻辑:

The Place class would be the same one as in the answer from Rob, but with decoding and encoding logic:

class Place: NSObject, MKAnnotation, Codable {
    let id: Int
    let type: PlaceType
    let latitude: Double
    let longitude: Double
    dynamic var title: String?
    
    lazy var coordinate: CLLocationCoordinate2D = {
        CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
    }()

    init(id: Int, title: String, latitude: Double, longitude: Double, type: PlaceType) {
        self.id = id
        self.type = type
        self.title = title
        self.latitude = latitude
        self.longitude = longitude

        super.init()
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        // Try to decode each place type id to see which place type the data is for
        var type: PlaceType? = nil
        var tempID: Int? = nil
        PlaceType.allCases.forEach { placeType in
            if let id = try? container.decode(Int.self, forKey: placeType.codingKey) {
                type = placeType
                tempID = id
            }
        }

        guard let decodedType = type, let decodedID = tempID  else {
            let context = DecodingError.Context(
                codingPath: decoder.codingPath,
                debugDescription: "Data does not have data for any of existing place types"
            )
            throw DecodingError.valueNotFound(Place.self, context)
        }
        self.type = decodedType
        self.id = decodedID

        self.title = try container.decode(String.self, forKey: .title)
        self.latitude = try container.decode(Double.self, forKey: .latitude)
        self.longitude = try container.decode(Double.self, forKey: .longitude)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: type.codingKey)
        try container.encode(title, forKey: .title)
        try container.encode(latitude, forKey: .latitude)
        try container.encode(longitude, forKey: .longitude)
    }

    enum CodingKeys: String, CodingKey {
        case shop_id, community_id, circuit_id, cyclist_id
        case title, latitude, longitude
    }
}

您可以在此处看到完整的工作代码.如果您不了解某些代码,请随时在Github中询问有关代码的问题.

You can see the complete working code here. Feel free to ask questions in Github about the code if you do not understand something.

这篇关于调用urlsession数据后重新加载映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆