无法使用 mapKit 将坐标从 ViewController 发送到另一个使用委托的 viewController
Unable to send coordinates from ViewController with mapKit to another viewController with delegate
我是 Swift 和 iOS 开发的新手。我有一个问题,我通过标签栏导航控制器连接了三个 viewController。第一个 viewController 目前是空的,没有被使用。在 secondViewController 中,我使用来自天气 API 的数据更新 UI。在 thirdViewController 中,我有一张地图。当我访问地图时,我需要坐标来更新 secondViewController 中的 url。
我想要实现的是在 thirdViewController 中检索当前的纬度和经度(没问题),但我无法通过委托发送这些值以触发 secondViewController 中的函数,因此更新那里的变量。 secondViewController 中的委托函数不会被触发。我究竟做错了什么?或者甚至可以这样做吗?
两个viewController的代码如下:
secondViewController(这是我需要 thirdViewController 中地图的值的地方)
import UIKit
class SecondViewController: UIViewController, MapViewControllerDelegate {
var forecastData: [ForecastData] = []
var currentLat: String = "59.911166"
var currentLon: String = "10.744810"
@IBOutlet weak var tableView: UITableView!
var weatherManager = WeatherManager()
var mapViewController = ThirdViewController()
override func viewDidLoad() {
super.viewDidLoad()
mapViewController.delegate = self
weatherManager.delegate = self
weatherManager.fetchWeather(latitude: currentLat, longitude: currentLon)
tableView.backgroundView = UIImageView(image: UIImage(named: "background"))
tableView.dataSource = self
tableView.register(UINib(nibName: "WeatherCell", bundle: nil), forCellReuseIdentifier: "WeatherCell")
}
func viewDidAppear() {
weatherManager.fetchWeather(latitude: currentLat, longitude: currentLon)
}
// THIS FUNCTION SHOULD BE TRIGGERED BUT DOESN'T
func mapViewController(latitude: String, longitude: String) {
currentLat = latitude
currentLon = longitude
print(currentLat)
print(currentLon)
print("DELEGATE METHOD TRIGGERED")
}
}
//MARK: - WeatherManagerDelegate
extension SecondViewController: WeatherManagerDelegate {
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel) {
forecastData.append(ForecastData(timespan: "Nå", precipitation: "", tempOrWeather: "Temperatur", tempWeatherLabel: "\(weather.temperatureNow)" + " " + "\(weather.tempUnits)"))
forecastData.append(ForecastData(timespan: "Neste Time", precipitation: "\(weather.precipitationNext1H)" + " " + "\(weather.precipUnits)", tempOrWeather: "vær", tempWeatherLabel: String(weather.conditionNext1H) ))
forecastData.append(ForecastData(timespan: "Neste 6 timer", precipitation: "\(weather.precipitationNext6H)" + " " + "\(weather.precipUnits)", tempOrWeather: "vær", tempWeatherLabel: String(weather.conditionNext6H)))
forecastData.append(ForecastData(timespan: "Neste 12 timer", precipitation: "", tempOrWeather: "vær", tempWeatherLabel: String(weather.conditionNext12H)))
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
func didFailWithError(error: Error) {
print(error)
}
}
extension SecondViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return forecastData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "WeatherCell", for: indexPath)
as! WeatherCell
cell.TimeframeLabel.text = forecastData[indexPath.row].TimeframeLabel
cell.TempLabel.text = forecastData[indexPath.row].TempLabel
cell.WeatherCodeLabel.text = forecastData[indexPath.row].WeatherCodeLabel
cell.PrecipitationLabel.text = forecastData[indexPath.row].PrecipitationLabel
return cell
}
}
thirdViewController(这是我尝试通过委托传递坐标值的地方)
import UIKit
import MapKit
import CoreLocation
protocol MapViewControllerDelegate {
func mapViewController(latitude: String, longitude: String)
}
class ThirdViewController: UIViewController, MKMapViewDelegate {
var currentLat = ""
var currentLon = ""
@IBOutlet weak var mMapView: MKMapView!
fileprivate let locationManager: CLLocationManager = CLLocationManager()
var delegate: MapViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.startUpdatingLocation()
mMapView.showsUserLocation = true
currentLat = String((locationManager.location?.coordinate.latitude)!)
currentLon = String((locationManager.location?.coordinate.longitude)!)
print(currentLat)
print(currentLon)
//delegate?.mapViewController(latitude: "TESTlon", longitude: "TESTlati")
}
override func viewDidAppear(_ animated: Bool) {
updateWeatherView()
}
// THIS SHOULD TRIGGER THE DELEGATE FUNCTION IN SECOND VIEW CONTROLLER AND PASS THE DATA ALONG
func updateWeatherView() {
delegate?.mapViewController(latitude: "TESTlon", longitude: "TESTlati")
}
}
我尝试了不同的方法,但似乎没有任何效果,secondViewController 中的委托函数只是没有被触发。同样,我对此很陌生,所以也许这是一件简单的事情。在此先感谢您的帮助!另外,如果有帮助的话,这是我的故事板的截图:
正如@Duncan C 所说,正在做
var weatherManager = WeatherManager()
var mapViewController = ThirdViewController()
只是为那些视图控制器创建了一个新实例——它们与您已有的完全无关。当然,如果你这样做 mapViewController.delegate = self
,你正在设置 mapViewController
的委托......但是 mapViewController
是 而不是 你想要的视图控制器。
要获得您想要的视图控制器,您可以访问选项卡栏控制器的视图控制器(当您在情节提要中创建它们时,它们会自动为您创建),然后选择正确的:
if
let viewControllers = self.tabBarController?.viewControllers,
viewControllers.count >= 3,
let thirdViewController = viewControllers[2] as? ThirdViewController /// [2] because that's the third view controller in the array, which is the one you want
{
thirdViewController.delegate = self
}
self.tabBarController
可能是 nil,所以你需要解包它。然后,你应该确保有超过 3 个视图控制器。最后,您需要将您需要的视图控制器 (self.tabBarController?.viewControllers[2]
) 转换为 ThirdViewController
。然后您可以将委托设置为该视图控制器。
我是 Swift 和 iOS 开发的新手。我有一个问题,我通过标签栏导航控制器连接了三个 viewController。第一个 viewController 目前是空的,没有被使用。在 secondViewController 中,我使用来自天气 API 的数据更新 UI。在 thirdViewController 中,我有一张地图。当我访问地图时,我需要坐标来更新 secondViewController 中的 url。
我想要实现的是在 thirdViewController 中检索当前的纬度和经度(没问题),但我无法通过委托发送这些值以触发 secondViewController 中的函数,因此更新那里的变量。 secondViewController 中的委托函数不会被触发。我究竟做错了什么?或者甚至可以这样做吗?
两个viewController的代码如下:
secondViewController(这是我需要 thirdViewController 中地图的值的地方)
import UIKit
class SecondViewController: UIViewController, MapViewControllerDelegate {
var forecastData: [ForecastData] = []
var currentLat: String = "59.911166"
var currentLon: String = "10.744810"
@IBOutlet weak var tableView: UITableView!
var weatherManager = WeatherManager()
var mapViewController = ThirdViewController()
override func viewDidLoad() {
super.viewDidLoad()
mapViewController.delegate = self
weatherManager.delegate = self
weatherManager.fetchWeather(latitude: currentLat, longitude: currentLon)
tableView.backgroundView = UIImageView(image: UIImage(named: "background"))
tableView.dataSource = self
tableView.register(UINib(nibName: "WeatherCell", bundle: nil), forCellReuseIdentifier: "WeatherCell")
}
func viewDidAppear() {
weatherManager.fetchWeather(latitude: currentLat, longitude: currentLon)
}
// THIS FUNCTION SHOULD BE TRIGGERED BUT DOESN'T
func mapViewController(latitude: String, longitude: String) {
currentLat = latitude
currentLon = longitude
print(currentLat)
print(currentLon)
print("DELEGATE METHOD TRIGGERED")
}
}
//MARK: - WeatherManagerDelegate
extension SecondViewController: WeatherManagerDelegate {
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel) {
forecastData.append(ForecastData(timespan: "Nå", precipitation: "", tempOrWeather: "Temperatur", tempWeatherLabel: "\(weather.temperatureNow)" + " " + "\(weather.tempUnits)"))
forecastData.append(ForecastData(timespan: "Neste Time", precipitation: "\(weather.precipitationNext1H)" + " " + "\(weather.precipUnits)", tempOrWeather: "vær", tempWeatherLabel: String(weather.conditionNext1H) ))
forecastData.append(ForecastData(timespan: "Neste 6 timer", precipitation: "\(weather.precipitationNext6H)" + " " + "\(weather.precipUnits)", tempOrWeather: "vær", tempWeatherLabel: String(weather.conditionNext6H)))
forecastData.append(ForecastData(timespan: "Neste 12 timer", precipitation: "", tempOrWeather: "vær", tempWeatherLabel: String(weather.conditionNext12H)))
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
func didFailWithError(error: Error) {
print(error)
}
}
extension SecondViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return forecastData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "WeatherCell", for: indexPath)
as! WeatherCell
cell.TimeframeLabel.text = forecastData[indexPath.row].TimeframeLabel
cell.TempLabel.text = forecastData[indexPath.row].TempLabel
cell.WeatherCodeLabel.text = forecastData[indexPath.row].WeatherCodeLabel
cell.PrecipitationLabel.text = forecastData[indexPath.row].PrecipitationLabel
return cell
}
}
thirdViewController(这是我尝试通过委托传递坐标值的地方)
import UIKit
import MapKit
import CoreLocation
protocol MapViewControllerDelegate {
func mapViewController(latitude: String, longitude: String)
}
class ThirdViewController: UIViewController, MKMapViewDelegate {
var currentLat = ""
var currentLon = ""
@IBOutlet weak var mMapView: MKMapView!
fileprivate let locationManager: CLLocationManager = CLLocationManager()
var delegate: MapViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.startUpdatingLocation()
mMapView.showsUserLocation = true
currentLat = String((locationManager.location?.coordinate.latitude)!)
currentLon = String((locationManager.location?.coordinate.longitude)!)
print(currentLat)
print(currentLon)
//delegate?.mapViewController(latitude: "TESTlon", longitude: "TESTlati")
}
override func viewDidAppear(_ animated: Bool) {
updateWeatherView()
}
// THIS SHOULD TRIGGER THE DELEGATE FUNCTION IN SECOND VIEW CONTROLLER AND PASS THE DATA ALONG
func updateWeatherView() {
delegate?.mapViewController(latitude: "TESTlon", longitude: "TESTlati")
}
}
我尝试了不同的方法,但似乎没有任何效果,secondViewController 中的委托函数只是没有被触发。同样,我对此很陌生,所以也许这是一件简单的事情。在此先感谢您的帮助!另外,如果有帮助的话,这是我的故事板的截图:
正如@Duncan C 所说,正在做
var weatherManager = WeatherManager()
var mapViewController = ThirdViewController()
只是为那些视图控制器创建了一个新实例——它们与您已有的完全无关。当然,如果你这样做 mapViewController.delegate = self
,你正在设置 mapViewController
的委托......但是 mapViewController
是 而不是 你想要的视图控制器。
要获得您想要的视图控制器,您可以访问选项卡栏控制器的视图控制器(当您在情节提要中创建它们时,它们会自动为您创建),然后选择正确的:
if
let viewControllers = self.tabBarController?.viewControllers,
viewControllers.count >= 3,
let thirdViewController = viewControllers[2] as? ThirdViewController /// [2] because that's the third view controller in the array, which is the one you want
{
thirdViewController.delegate = self
}
self.tabBarController
可能是 nil,所以你需要解包它。然后,你应该确保有超过 3 个视图控制器。最后,您需要将您需要的视图控制器 (self.tabBarController?.viewControllers[2]
) 转换为 ThirdViewController
。然后您可以将委托设置为该视图控制器。