从另一个视图控制器更新视图控制器的内容而不打开它

时间:2016-06-03 12:48:16

标签: ios swift

在我正在开发的应用程序中,我需要在点击按钮时更新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

}

2 个答案:

答案 0 :(得分:1)

为什么不在viewController2viewWillAppear更新viewDidLoad的内容?视图控制器不会加载其视图和子视图,直到它需要在屏幕上显示它们。  因此,如果您不打算显示viewController2的{​​{1}}视图,那么这就是为什么你没有,你无法访问它。

实现目标的干净方法是:

  1. viewController2中有一个单独的属性来存储数据

  2. viewController1

  3. 中设置属性的内容
  4. 然后根据您刚设置的属性更新viewController2viewDidLoadviewWillAppear的视图。

  5. 修改

    尝试更改此内容:

    if self.delegate2 != nil
            {
                dispatch_async(dispatch_get_main_queue(), {
                    self.delegate2?.SetForecast(forecast)
                })
            }
    

    if self.delegate2 != nil
        {
            self.delegate2?.SetForecast(forecast)
    
        }
    

    异步块内的代码将异步执行,因此在设置这些属性之前,可以将viewWillAppearviewDidload称为。 这就是为什么这些值是“”。此外,这里不需要使用异步块,你在SetForcast中所做的只是设置属性值,它们几乎立即完成。

答案 1 :(得分:0)

你根本无法做到这一点。

如果未加载ViewController2,则 永远不会获取数据。

首先必须对其进行初始化,然后您可以为其提供数据,而无需显示

你只需要做一个" alloc-init"将其加载到变量中。你提供数据。