在我正在开发的应用程序中,我需要在点击按钮时更新2个视图控制器。我设法更新包含按钮的视图控制器,但我无法更新其他视图控制器的内容。
我尝试通过以下两种方式实现:首先,我在按钮的视图控制器中创建了一个委托变量(使用协议),并将其值设置为另一个视图控制器:
var delegate: WeatherServiceDelegateForcast? = ViewController2()
因为ViewController2是我试图使用委托更新的视图控制器。
协议:
protocol WeatherServiceDelegateForcast{
func SetForcast(forcast: ForcastInfo)
}
viewController2中的SetForcast功能
func SetForcast(forcast: ForcastInfo) {
self.day1Label.text = ....
}
问题在于,当执行函数SetForcast时,day1label的IBOutlet为nil,因此无法更新。我想这是因为视图控制器尚未加载,但我无法找到加载它的方法。
其次,我尝试使用segue(没有委托)将数据传递给viewcontroller2。这有效,但只有当我使用类型show为segue和我的应用程序时,它是不会打开它是至关重要的。当我尝试使用segue而不打开viewcontroller2(按类型自定义)时,它再次无效并无法识别IBOutlets。
如何在不打开数据的情况下将数据传递给viewcontroller2的任何建议?
修改
这是我使用的代码:
当点击viewcontroller1中的按钮时,它从文本字段中获取数据并从其属性气象服务中调用该函数(可行)。
self.weatherService.GetForcast(textField.text!)
GetWeather获取城市的天气,从类型预测中创建变量,然后:
if self.delegate2 != nil
{
dispatch_async(dispatch_get_main_queue(), {
self.delegate2?.SetForecast(forecast)
})
}
因为delegate2是weatherService的属性,它引用了viewcontroller2,这就是它在weatherService类的开头定义的方式:
var delegate2: WeatherServiceDelegateForecast? = ViewController2()
和WeatherServiceForcast是协议:
protocol WeatherServiceDelegateForcast
{
func SetForecast(forecast: ForecastInfo)
}
然后,根据调试器,它使用正确的预测变量执行viewcontroller2的SetForecast:
func SetForcast(forcast: ForcastInfo) {
self.day1 = String(round(forcast.day[0])) + "-" + String(round(forcast.night[0]))
self.day2 = String(round(forcast.day[1])) + "-" + String(round(forcast.night[1]))
self.day3 = String(round(forcast.day[2])) + "-" + String(round(forcast.night[2]))
self.day4 = String(round(forcast.day[3])) + "-" + String(round(forcast.night[3]))
self.day5 = String(round(forcast.day[4])) + "-" + String(round(forcast.night[4]))
self.day6 = String(round(forcast.day[5])) + "-" + String(round(forcast.night[5]))
self.day7 = String(round(forcast.day[6])) + "-" + String(round(forcast.night[6]))
}
as day1-7是viewController2类中的变量,之后我想更新viewController2的标签,这就是这些变量的定义方式:
var day1 = String()
var day2 = String()
var day3 = String()
var day4 = String()
var day5 = String()
var day6 = String()
var day7 = String()
在viewDidLoad中我把代码更新为变量day1-7的字符串,但似乎它首先调用该函数,然后才调用set forecast并更新变量。
override func viewDidLoad() {
// Do any additional setup after loading the view.
self.day1Label.text = self.day1
self.day2Label.text = self.day2
self.day3Label.text = self.day3
self.day4Label.text = self.day4
self.day5Label.text = self.day5
self.day6Label.text = self.day6
self.day7Label.text = self.day7
}
答案 0 :(得分:1)
为什么不在viewController2
或viewWillAppear
更新viewDidLoad
的内容?视图控制器不会加载其视图和子视图,直到它需要在屏幕上显示它们。
因此,如果您不打算显示viewController2
的{{1}}视图,那么这就是为什么你没有,你无法访问它。
实现目标的干净方法是:
在viewController2
中有一个单独的属性来存储数据
在viewController1
然后根据您刚设置的属性更新viewController2
或viewDidLoad
中viewWillAppear
的视图。
修改强>
尝试更改此内容:
if self.delegate2 != nil
{
dispatch_async(dispatch_get_main_queue(), {
self.delegate2?.SetForecast(forecast)
})
}
到
if self.delegate2 != nil
{
self.delegate2?.SetForecast(forecast)
}
异步块内的代码将异步执行,因此在设置这些属性之前,可以将viewWillAppear
或viewDidload
称为。
这就是为什么这些值是“”。此外,这里不需要使用异步块,你在SetForcast
中所做的只是设置属性值,它们几乎立即完成。
答案 1 :(得分:0)
你根本无法做到这一点。
如果未加载ViewController2
,则 永远不会获取数据。
首先必须对其进行初始化,然后您可以为其提供数据,而无需显示。
你只需要做一个" alloc-init"将其加载到变量中。你提供数据。