为什么数组 return 在 Swift 中为空?
Why does the Array return empty in Swift?
我正在尝试向我的 MapKit
添加注释,但是我附加到的数组返回 nil。我之前使用这种方法在之前的 ViewControllers
中填充 CollectionView
并且数组有值,现在如果我打印数组它 returns 0 值,我确信应该有数据,因为它打印在控制台中,但未添加到数组中。请考虑一下?
我的经理Class:
class GoogleMapsAPIManager {
var bloodBanksArray = [BloodBanksModel]()
func fetchCity(latitude: CLLocationDegrees, longitude: CLLocationDegrees, raduis: Double){
let urlString = "\(K.googleMapsAPI)&location=\(latitude),\(longitude)&radius=\(raduis)&key=\(K.apiKey)"
print(urlString)
performRequest(with: urlString)
}
//MARK: - Decoding JSON
func performRequest(with urlString: String){
if let url = URL(string: urlString) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!)
return
}
if let safeData = data {
self.parseJSON(bloodBankData: safeData)
}
}
task.resume()
}
}
func parseJSON(bloodBankData: Data) {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(BloodBanksData.self, from: bloodBankData)
for i in 0...decodedData.results.count - 1 {
bloodBanksArray.append(BloodBanksModel(name: decodedData.results[i].name, photo: decodedData.results[i].photos?[0].photoReference ?? "ATtYBwJjqXlw3DMdL74SRtgG_GRA3LkAET6hDJXHWtkQMaOTo1B3Gx9jrDTXFLFabGStSxX8BiYdLAnknF7A9ynw33KKyUh5Oc55A9vXzo_6nd4mnk5Sx-iOqMNaw21dk0C424PWaio9GiogQaKecYxOT1q-bmj30syypZmyxkjF7r3-gFyC", open_now: decodedData.results[i].openingHours?.openNow ?? false, vincinity: decodedData.results[i].vicinity, rating: decodedData.results[i].rating, placeId: decodedData.results[i].placeId, lat: decodedData.results[i].geometry.location.lat, lng: decodedData.results[i].geometry.location.lng))
}
print("bossins \(bloodBanksArray)")
} catch {
print(error)
}
}
}
型号Class:
struct BloodBanksModel {
let name: String
let photo: String
let open_now: Bool
let vincinity: String
let rating: Double
let placeId: String
let lat: Double
let lng: Double
}
数据:
import Foundation
// MARK: - BloodBanksData
struct BloodBanksData: Codable {
let results: [Result]
enum CodingKeys: String, CodingKey {
case results
}
}
// MARK: - Result
struct Result: Codable {
let geometry: Geometry
let name: String
let openingHours: OpeningHours?
let photos: [Photo]?
let rating: Double
let vicinity: String
let placeId: String
enum CodingKeys: String, CodingKey {
case geometry, name
case openingHours = "opening_hours"
case photos
case rating
case vicinity
case placeId = "place_id"
}
}
// MARK: - Geometry
struct Geometry: Codable {
let location: Location
}
// MARK: - Location
struct Location: Codable {
let lat, lng: Double
}
// MARK: - OpeningHours
struct OpeningHours: Codable {
let openNow: Bool
enum CodingKeys: String, CodingKey {
case openNow = "open_now"
}
}
// MARK: - Photo
struct Photo: Codable {
let photoReference: String
enum CodingKeys: String, CodingKey {
case photoReference = "photo_reference"
}
}
在我的 ViewController:
override func viewDidLoad() {
super.viewDidLoad()
//mapView.delegate = self
locationManager.requestWhenInUseAuthorization()
var currentLocation: CLLocation!
if
CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == .authorizedAlways
{
currentLocation = locationManager.location
googleMapsAPIManager.fetchCity(latitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude, raduis: 100000.0)
}
for location in googleMapsAPIManager.bloodBanksArray {
let annotation = MKPointAnnotation()
annotation.title = location.name
annotation.coordinate = CLLocationCoordinate2D(latitude: location.lat, longitude: location.lng)
annotations.append(annotation)
}
mapView.addAnnotations(annotations)
}
正如我在你的 previous question fetchCity
作品中所说 异步 ,你必须添加一个完成处理程序
为了方便起见,我将 fetchCity
、performRequest
和 parseJSON()
合并为一个方法。
func fetchCity(latitude: CLLocationDegrees, longitude: CLLocationDegrees, raduis: Double, completion: @escaping () -> Void){
let urlString = "\(K.googleMapsAPI)&location=\(latitude),\(longitude)&radius=\(raduis)&key=\(K.apiKey)"
print(urlString)
if let url = URL(string: urlString) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, _, error) in
if let error = error { print(error); return }
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(BloodBanksData.self, from: data!)
for i in 0..<decodedData.results.count {
bloodBanksArray.append(BloodBanksModel(name: decodedData.results[i].name, photo: decodedData.results[i].photos?[0].photoReference ?? "ATtYBwJjqXlw3DMdL74SRtgG_GRA3LkAET6hDJXHWtkQMaOTo1B3Gx9jrDTXFLFabGStSxX8BiYdLAnknF7A9ynw33KKyUh5Oc55A9vXzo_6nd4mnk5Sx-iOqMNaw21dk0C424PWaio9GiogQaKecYxOT1q-bmj30syypZmyxkjF7r3-gFyC", open_now: decodedData.results[i].openingHours?.openNow ?? false, vincinity: decodedData.results[i].vicinity, rating: decodedData.results[i].rating, placeId: decodedData.results[i].placeId, lat: decodedData.results[i].geometry.location.lat, lng: decodedData.results[i].geometry.location.lng))
}
print("bossins \(bloodBanksArray)")
completion()
} catch {
print(error)
}
}
task.resume()
}
}
并称之为
if CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == .authorizedAlways {
currentLocation = locationManager.location
googleMapsAPIManager.fetchCity(latitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude, raduis: 100000.0) {
for location in googleMapsAPIManager.bloodBanksArray {
let annotation = MKPointAnnotation()
annotation.title = location.name
annotation.coordinate = CLLocationCoordinate2D(latitude: location.lat, longitude: location.lng)
annotations.append(annotation)
}
mapView.addAnnotations(annotations)
}
}
请注意,Core Location 也是异步工作的。
我正在尝试向我的 MapKit
添加注释,但是我附加到的数组返回 nil。我之前使用这种方法在之前的 ViewControllers
中填充 CollectionView
并且数组有值,现在如果我打印数组它 returns 0 值,我确信应该有数据,因为它打印在控制台中,但未添加到数组中。请考虑一下?
我的经理Class:
class GoogleMapsAPIManager {
var bloodBanksArray = [BloodBanksModel]()
func fetchCity(latitude: CLLocationDegrees, longitude: CLLocationDegrees, raduis: Double){
let urlString = "\(K.googleMapsAPI)&location=\(latitude),\(longitude)&radius=\(raduis)&key=\(K.apiKey)"
print(urlString)
performRequest(with: urlString)
}
//MARK: - Decoding JSON
func performRequest(with urlString: String){
if let url = URL(string: urlString) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!)
return
}
if let safeData = data {
self.parseJSON(bloodBankData: safeData)
}
}
task.resume()
}
}
func parseJSON(bloodBankData: Data) {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(BloodBanksData.self, from: bloodBankData)
for i in 0...decodedData.results.count - 1 {
bloodBanksArray.append(BloodBanksModel(name: decodedData.results[i].name, photo: decodedData.results[i].photos?[0].photoReference ?? "ATtYBwJjqXlw3DMdL74SRtgG_GRA3LkAET6hDJXHWtkQMaOTo1B3Gx9jrDTXFLFabGStSxX8BiYdLAnknF7A9ynw33KKyUh5Oc55A9vXzo_6nd4mnk5Sx-iOqMNaw21dk0C424PWaio9GiogQaKecYxOT1q-bmj30syypZmyxkjF7r3-gFyC", open_now: decodedData.results[i].openingHours?.openNow ?? false, vincinity: decodedData.results[i].vicinity, rating: decodedData.results[i].rating, placeId: decodedData.results[i].placeId, lat: decodedData.results[i].geometry.location.lat, lng: decodedData.results[i].geometry.location.lng))
}
print("bossins \(bloodBanksArray)")
} catch {
print(error)
}
}
}
型号Class:
struct BloodBanksModel {
let name: String
let photo: String
let open_now: Bool
let vincinity: String
let rating: Double
let placeId: String
let lat: Double
let lng: Double
}
数据:
import Foundation
// MARK: - BloodBanksData
struct BloodBanksData: Codable {
let results: [Result]
enum CodingKeys: String, CodingKey {
case results
}
}
// MARK: - Result
struct Result: Codable {
let geometry: Geometry
let name: String
let openingHours: OpeningHours?
let photos: [Photo]?
let rating: Double
let vicinity: String
let placeId: String
enum CodingKeys: String, CodingKey {
case geometry, name
case openingHours = "opening_hours"
case photos
case rating
case vicinity
case placeId = "place_id"
}
}
// MARK: - Geometry
struct Geometry: Codable {
let location: Location
}
// MARK: - Location
struct Location: Codable {
let lat, lng: Double
}
// MARK: - OpeningHours
struct OpeningHours: Codable {
let openNow: Bool
enum CodingKeys: String, CodingKey {
case openNow = "open_now"
}
}
// MARK: - Photo
struct Photo: Codable {
let photoReference: String
enum CodingKeys: String, CodingKey {
case photoReference = "photo_reference"
}
}
在我的 ViewController:
override func viewDidLoad() {
super.viewDidLoad()
//mapView.delegate = self
locationManager.requestWhenInUseAuthorization()
var currentLocation: CLLocation!
if
CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == .authorizedAlways
{
currentLocation = locationManager.location
googleMapsAPIManager.fetchCity(latitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude, raduis: 100000.0)
}
for location in googleMapsAPIManager.bloodBanksArray {
let annotation = MKPointAnnotation()
annotation.title = location.name
annotation.coordinate = CLLocationCoordinate2D(latitude: location.lat, longitude: location.lng)
annotations.append(annotation)
}
mapView.addAnnotations(annotations)
}
正如我在你的 previous question fetchCity
作品中所说 异步 ,你必须添加一个完成处理程序
为了方便起见,我将 fetchCity
、performRequest
和 parseJSON()
合并为一个方法。
func fetchCity(latitude: CLLocationDegrees, longitude: CLLocationDegrees, raduis: Double, completion: @escaping () -> Void){
let urlString = "\(K.googleMapsAPI)&location=\(latitude),\(longitude)&radius=\(raduis)&key=\(K.apiKey)"
print(urlString)
if let url = URL(string: urlString) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, _, error) in
if let error = error { print(error); return }
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(BloodBanksData.self, from: data!)
for i in 0..<decodedData.results.count {
bloodBanksArray.append(BloodBanksModel(name: decodedData.results[i].name, photo: decodedData.results[i].photos?[0].photoReference ?? "ATtYBwJjqXlw3DMdL74SRtgG_GRA3LkAET6hDJXHWtkQMaOTo1B3Gx9jrDTXFLFabGStSxX8BiYdLAnknF7A9ynw33KKyUh5Oc55A9vXzo_6nd4mnk5Sx-iOqMNaw21dk0C424PWaio9GiogQaKecYxOT1q-bmj30syypZmyxkjF7r3-gFyC", open_now: decodedData.results[i].openingHours?.openNow ?? false, vincinity: decodedData.results[i].vicinity, rating: decodedData.results[i].rating, placeId: decodedData.results[i].placeId, lat: decodedData.results[i].geometry.location.lat, lng: decodedData.results[i].geometry.location.lng))
}
print("bossins \(bloodBanksArray)")
completion()
} catch {
print(error)
}
}
task.resume()
}
}
并称之为
if CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == .authorizedAlways {
currentLocation = locationManager.location
googleMapsAPIManager.fetchCity(latitude: currentLocation.coordinate.latitude, longitude: currentLocation.coordinate.longitude, raduis: 100000.0) {
for location in googleMapsAPIManager.bloodBanksArray {
let annotation = MKPointAnnotation()
annotation.title = location.name
annotation.coordinate = CLLocationCoordinate2D(latitude: location.lat, longitude: location.lng)
annotations.append(annotation)
}
mapView.addAnnotations(annotations)
}
}
请注意,Core Location 也是异步工作的。