从 API 检索数据以在数组中使用它们时,如何摆脱“必须从主线程调用 API 方法”的问题?斯威夫特

问题描述 投票:0回答:1

我来找你是因为我有以下问题:

我使用“GoogleMaps”cocoapods,需要使用从 API 获取的纬度、经度和 codeID 在地图中放置多个标记。我将向大家展示 2 种情况:一种有效(使用前面提到的 3 个硬编码数组),另一种是我尝试从 API 获取但无论我做什么都会崩溃的情况。好的,第一个案例(有效的案例)就是这个:

import UIKit
import GoogleMaps

class ViewController: UIViewController {
// MARK: - Constants and variables
let lat: Double = 38.739429 // User's Latitude
let lon: Double = -9.137115 // User's Longitude
let zoom: Float = 15.0

// MARK: - Elements in the storyboard
@IBOutlet weak var googleMap: GMSMapView!

// MARK: - ViewDidLoad()
override func viewDidLoad() {
    super.viewDidLoad()
    googleMapsStuff()
}

// MARK: - Google maps method
func googleMapsStuff() {
    googleMap.delegate = self
    self.googleMap.isMyLocationEnabled = true // User's current position (blue dot on the map)
    let arrayLat: [Double] = [38.739, 38.74, 38.741, 38.732, 38.7325, 38.733]
    let arrayLon: [Double] = [-9.136, -9.135, -9.134, -9.137, -9.1375, -9.138]
    //var arrayCompanyZoneID: [Int] = []
    let camera: GMSCameraPosition = GMSCameraPosition.camera(withLatitude: lat, longitude: lon, zoom: self.zoom)

    googleMap.camera = camera
    
    for index in 0..<arrayLon.count {
        let marker = GMSMarker()
        marker.position = CLLocationCoordinate2D(latitude: arrayLat[index], longitude: arrayLon[index])
        marker.title = "Marker number: \(index)"
        marker.snippet = "Marker's Lat: \(arrayLat[index]), Marker's Lon: \(arrayLon[index])"
        marker.map = self.googleMap
        print("Index: \(index)")
    }
}
}

正如您在图片中看到的,一切都很顺利:

ScreenShotGood

问题出现在第二种情况下,当我连接到 API 来获取数据时尝试填充空数组(看起来确实如此)。这是“失败”的案例:

struct MyInfo: Codable {
let id: String
let name: String
let x: Double // Longitude
let y: Double // Latitude
let licencePlate: String?
let range: Int?
let batteryLevel: Int?
let seats: Int?
let model: String?
let resourceImageId: String?
let pricePerMinuteParking: Int?
let pricePerMinuteDriving: Int?
let realTimeData: Bool?
let engineType: String?
let resourceType: String?
let companyZoneId: Int
let helmets: Int?
let station: Bool?
let availableResources: Int?
let spacesAvailable: Int?
let allowDropoff: Bool?
let bikesAvailable: Int?
}

class ViewController: UIViewController {
// MARK: - Constants and variables
let lat: Double = 38.739429 // User's Latitude
let lon: Double = -9.137115 // User's Longitude
let zoom: Float = 15.0
var arrayLat: [Double] = [] // [38.7395, 38.739, 38.74, 38.741, 38.732, 38.7325, 38.733]
var arrayLon: [Double] = [] // [-9.1365, -9.136, -9.135, -9.134, -9.137, -9.1375, -9.138]
var arrayCompanyZoneID: [Int] = [] // [1, 2, 3, 4, 5, 6, 7]

// MARK: - Elements in the storyboard
@IBOutlet weak var googleMap: GMSMapView!

// MARK: - ViewDidLoad()
override func viewDidLoad() {
    super.viewDidLoad()
    googleMap.delegate = self
    
    self.googleMap.isMyLocationEnabled = true // User's current position (blue dot on the map)
    let camera: GMSCameraPosition = GMSCameraPosition.camera(withLatitude: self.lat, longitude: self.lon, zoom: self.zoom)

    googleMap.camera = camera
    
    guard let urlAPI = URL(string: "https://apidev.meep.me/tripplan/api/v1/routers/lisboa/resources?lowerLeftLatLon=38.711046,-9.160096&upperRightLatLon=38.739429,-9.137115") else { return }
    
    let task = URLSession.shared.dataTask(with: urlAPI) {(data, response, error) in
        if error == nil {
            guard let urlContent = data else { return }
            
            do {
                let JSONResult = try JSONDecoder().decode([MyInfo].self, from: urlContent) //JSONSerialization.jsonObject(with: urlContent, options: .mutableContainers)
                print("JSON Result:", JSONResult)
                
                for jsonData in JSONResult {
                    self.arrayLon.append(jsonData.x)
                    self.arrayLat.append(jsonData.y)
                    self.arrayCompanyZoneID.append(jsonData.companyZoneId)
                }
                
                print("-----------------")
                print(type(of: JSONResult))
                print("-----------------")
                print("ArrayLon:", self.arrayLon)
                print("ArrayLat:", self.arrayLat)
                print("companyZoneId: ", self.arrayCompanyZoneID)
                print("Count zoneid: ", self.arrayCompanyZoneID.count)
                print("-----------------")
                
                // MARK: - Place the multiple markers on the map
                for index in 0..<self.arrayCompanyZoneID.count {
                    let marker = GMSMarker()
                    marker.position = CLLocationCoordinate2D(latitude: self.arrayLat[index], longitude: self.arrayLon[index])
                    marker.title = "Marker number: \(index)"
                    marker.snippet = "Marker's Lat: \(self.arrayLat[index]), Marker's Lon: \(self.arrayLon[index])"
                    marker.map = self.googleMap
                    print("Index: \(index)")
                }
                
            } catch {
                print("JSON processing failed.")
            }
        } else {
            print("Error serializing JSON:", error!)
        }
    }
    
    task.resume()
}

无论我做什么,控制台总是说:

“由于未捕获的异常‘GMSThreadException’而终止应用程序,原因:‘API 方法必须从主线程调用’”

我也尝试过使用这个方法

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])

但它也说 API 方法大多数是从主线程调用的。

我被困在这里,我花了几个小时来解决这个问题,但它只是一遍又一遍地失败。

我感谢您的建议和智慧。

ios arrays swift
1个回答
1
投票

你需要

DispatchQueue.main.async {

            // MARK: - Place the multiple markers on the map
            for index in 0..<self.arrayCompanyZoneID.count {
                let marker = GMSMarker()
                marker.position = CLLocationCoordinate2D(latitude: self.arrayLat[index], longitude: self.arrayLon[index])
                marker.title = "Marker number: \(index)"
                marker.snippet = "Marker's Lat: \(self.arrayLat[index]), Marker's Lon: \(self.arrayLon[index])"
                marker.map = self.googleMap
                print("Index: \(index)")
            }
 }

由于

URLSession.shared.dataTask
回调位于后台线程中

© www.soinside.com 2019 - 2024. All rights reserved.