无法将坐标从带有mapKit的ViewController发送到带有委托的另一个viewController

问题描述

我是Swift和iOS开发的新手。我有一个问题,其中有三个通过选项卡栏导航控制器连接的viewControllers。第一个viewController目前为空,尚未使用。在secondViewController中,我使用天气API中的数据更新UI。在thirdViewController中,我有一张地图。当我访问地图时,我需要坐标来更新secondViewController中的网址。

我要实现的是在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)",tempWeatherLabel: String(weather.conditionNext6H)))
        
        forecastData.append(ForecastData(timespan: "neste 12 timer",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中的委托函数只是没有被触发。同样,我对此很陌生,所以也许这很简单。在此先感谢您的帮助!另外,如果有帮助,下面是我的故事板的屏幕截图:

Screenshot of storyboard

解决方法

正如@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可能为零,因此需要解开包装。然后,您应确保有3个以上的视图控制器。最后,您需要将所需的视图控制器(self.tabBarController?.viewControllers[2])强制转换为ThirdViewController。然后,您可以将委托设置为该视图控制器。