Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/105.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何在Swift中的视图控制器和其他对象之间共享数据?_Ios_Swift - Fatal编程技术网

Ios 如何在Swift中的视图控制器和其他对象之间共享数据?

Ios 如何在Swift中的视图控制器和其他对象之间共享数据?,ios,swift,Ios,Swift,假设我的Swift应用程序中有多个视图控制器,我希望能够在它们之间传递数据。如果我在一个视图控制器堆栈中处于几层以下,如何将数据传递给另一个视图控制器?或者在选项卡栏视图控制器中的选项卡之间 (注意,这个问题是一个“振铃器”。)它被问得太多了,以至于我决定写一篇关于这个主题的教程。请看下面我的答案。这个问题一直都会出现 一个建议是创建一个数据容器singleton:一个在应用程序生命周期中只创建一次的对象,并在应用程序生命周期中保持不变 这种方法非常适用于需要在应用程序中的不同类之间提供/修改全

假设我的Swift应用程序中有多个视图控制器,我希望能够在它们之间传递数据。如果我在一个视图控制器堆栈中处于几层以下,如何将数据传递给另一个视图控制器?或者在选项卡栏视图控制器中的选项卡之间


(注意,这个问题是一个“振铃器”。)它被问得太多了,以至于我决定写一篇关于这个主题的教程。请看下面我的答案。

这个问题一直都会出现

一个建议是创建一个数据容器singleton:一个在应用程序生命周期中只创建一次的对象,并在应用程序生命周期中保持不变

这种方法非常适用于需要在应用程序中的不同类之间提供/修改全局应用程序数据的情况

其他方法(如在视图控制器之间设置单向或双向链接)更适合在视图控制器之间直接传递信息/消息的情况

(其他备选方案见下文nhgrif的答案。)

使用数据容器singleton,可以向类中添加一个属性,该属性存储对singleton的引用,然后在需要访问时随时使用该属性

您可以设置singleton,使其将内容保存到磁盘,以便在两次启动之间保持应用程序状态

我在GitHub上创建了一个演示项目,演示了如何做到这一点。以下是链接:

以下是该项目的自述:

SwiftDataContainerSingleton 演示如何使用数据容器单例保存应用程序状态并在对象之间共享

DataContainerSingleton
类是实际的单例

它使用一个静态常量
sharedDataContainer
保存对singleton的引用

要访问singleton,请使用以下语法

DataContainerSingleton.sharedDataContainer
示例项目在数据容器中定义了3个属性:

  var someString: String?
  var someOtherString: String?
  var someInt: Int?
要从数据容器加载
someInt
属性,可以使用如下代码:

let theInt = DataContainerSingleton.sharedDataContainer.someInt
goToBackgroundObserver = NSNotificationCenter.defaultCenter().addObserverForName(
  UIApplicationDidEnterBackgroundNotification,
  object: nil,
  queue: nil)
  {
    (note: NSNotification!) -> Void in
    let defaults = NSUserDefaults.standardUserDefaults()
    //-----------------------------------------------------------------------------
    //This code saves the singleton's properties to NSUserDefaults.
    //edit this code to save your custom properties
    defaults.setObject( self.someString, forKey: DefaultsKeys.someString)
    defaults.setObject( self.someOtherString, forKey: DefaultsKeys.someOtherString)
    defaults.setObject( self.someInt, forKey: DefaultsKeys.someInt)
    //-----------------------------------------------------------------------------

    //Tell NSUserDefaults to save to disk now.
    defaults.synchronize()
}
let defaults = NSUserDefaults.standardUserDefaults()
//-----------------------------------------------------------------------------
//This code reads the singleton's properties from NSUserDefaults.
//edit this code to load your custom properties
someString = defaults.objectForKey(DefaultsKeys.someString) as! String?
someOtherString = defaults.objectForKey(DefaultsKeys.someOtherString) as! String?
someInt = defaults.objectForKey(DefaultsKeys.someInt) as! Int?
//-----------------------------------------------------------------------------
struct DefaultsKeys
{
  static let someString  = "someString"
  static let someOtherString  = "someOtherString"
  static let someInt  = "someInt"
}
DefaultsKeys.someInt
要将值保存到someInt,请使用以下语法:

DataContainerSingleton.sharedDataContainer.someInt = 3
DataContainerSingleton的
init
方法为
UIApplicationIdentinterBackgroundNotification
添加了一个观察者。该代码如下所示:

let theInt = DataContainerSingleton.sharedDataContainer.someInt
goToBackgroundObserver = NSNotificationCenter.defaultCenter().addObserverForName(
  UIApplicationDidEnterBackgroundNotification,
  object: nil,
  queue: nil)
  {
    (note: NSNotification!) -> Void in
    let defaults = NSUserDefaults.standardUserDefaults()
    //-----------------------------------------------------------------------------
    //This code saves the singleton's properties to NSUserDefaults.
    //edit this code to save your custom properties
    defaults.setObject( self.someString, forKey: DefaultsKeys.someString)
    defaults.setObject( self.someOtherString, forKey: DefaultsKeys.someOtherString)
    defaults.setObject( self.someInt, forKey: DefaultsKeys.someInt)
    //-----------------------------------------------------------------------------

    //Tell NSUserDefaults to save to disk now.
    defaults.synchronize()
}
let defaults = NSUserDefaults.standardUserDefaults()
//-----------------------------------------------------------------------------
//This code reads the singleton's properties from NSUserDefaults.
//edit this code to load your custom properties
someString = defaults.objectForKey(DefaultsKeys.someString) as! String?
someOtherString = defaults.objectForKey(DefaultsKeys.someOtherString) as! String?
someInt = defaults.objectForKey(DefaultsKeys.someInt) as! Int?
//-----------------------------------------------------------------------------
struct DefaultsKeys
{
  static let someString  = "someString"
  static let someOtherString  = "someOtherString"
  static let someInt  = "someInt"
}
DefaultsKeys.someInt
在观察者代码中,它将数据容器的属性保存到
NSUserDefaults
。您还可以使用
NSCoding
、核心数据或各种其他方法来保存状态数据

DataContainerSingleton的
init
方法还尝试为其属性加载保存的值

init方法的这一部分如下所示:

let theInt = DataContainerSingleton.sharedDataContainer.someInt
goToBackgroundObserver = NSNotificationCenter.defaultCenter().addObserverForName(
  UIApplicationDidEnterBackgroundNotification,
  object: nil,
  queue: nil)
  {
    (note: NSNotification!) -> Void in
    let defaults = NSUserDefaults.standardUserDefaults()
    //-----------------------------------------------------------------------------
    //This code saves the singleton's properties to NSUserDefaults.
    //edit this code to save your custom properties
    defaults.setObject( self.someString, forKey: DefaultsKeys.someString)
    defaults.setObject( self.someOtherString, forKey: DefaultsKeys.someOtherString)
    defaults.setObject( self.someInt, forKey: DefaultsKeys.someInt)
    //-----------------------------------------------------------------------------

    //Tell NSUserDefaults to save to disk now.
    defaults.synchronize()
}
let defaults = NSUserDefaults.standardUserDefaults()
//-----------------------------------------------------------------------------
//This code reads the singleton's properties from NSUserDefaults.
//edit this code to load your custom properties
someString = defaults.objectForKey(DefaultsKeys.someString) as! String?
someOtherString = defaults.objectForKey(DefaultsKeys.someOtherString) as! String?
someInt = defaults.objectForKey(DefaultsKeys.someInt) as! Int?
//-----------------------------------------------------------------------------
struct DefaultsKeys
{
  static let someString  = "someString"
  static let someOtherString  = "someOtherString"
  static let someInt  = "someInt"
}
DefaultsKeys.someInt
用于将值加载和保存到NSUserDefaults中的键存储为字符串常量,这些常量是struct
DefaultsKeys
的一部分,定义如下:

let theInt = DataContainerSingleton.sharedDataContainer.someInt
goToBackgroundObserver = NSNotificationCenter.defaultCenter().addObserverForName(
  UIApplicationDidEnterBackgroundNotification,
  object: nil,
  queue: nil)
  {
    (note: NSNotification!) -> Void in
    let defaults = NSUserDefaults.standardUserDefaults()
    //-----------------------------------------------------------------------------
    //This code saves the singleton's properties to NSUserDefaults.
    //edit this code to save your custom properties
    defaults.setObject( self.someString, forKey: DefaultsKeys.someString)
    defaults.setObject( self.someOtherString, forKey: DefaultsKeys.someOtherString)
    defaults.setObject( self.someInt, forKey: DefaultsKeys.someInt)
    //-----------------------------------------------------------------------------

    //Tell NSUserDefaults to save to disk now.
    defaults.synchronize()
}
let defaults = NSUserDefaults.standardUserDefaults()
//-----------------------------------------------------------------------------
//This code reads the singleton's properties from NSUserDefaults.
//edit this code to load your custom properties
someString = defaults.objectForKey(DefaultsKeys.someString) as! String?
someOtherString = defaults.objectForKey(DefaultsKeys.someOtherString) as! String?
someInt = defaults.objectForKey(DefaultsKeys.someInt) as! Int?
//-----------------------------------------------------------------------------
struct DefaultsKeys
{
  static let someString  = "someString"
  static let someOtherString  = "someOtherString"
  static let someInt  = "someInt"
}
DefaultsKeys.someInt
您可以这样引用其中一个常量:

let theInt = DataContainerSingleton.sharedDataContainer.someInt
goToBackgroundObserver = NSNotificationCenter.defaultCenter().addObserverForName(
  UIApplicationDidEnterBackgroundNotification,
  object: nil,
  queue: nil)
  {
    (note: NSNotification!) -> Void in
    let defaults = NSUserDefaults.standardUserDefaults()
    //-----------------------------------------------------------------------------
    //This code saves the singleton's properties to NSUserDefaults.
    //edit this code to save your custom properties
    defaults.setObject( self.someString, forKey: DefaultsKeys.someString)
    defaults.setObject( self.someOtherString, forKey: DefaultsKeys.someOtherString)
    defaults.setObject( self.someInt, forKey: DefaultsKeys.someInt)
    //-----------------------------------------------------------------------------

    //Tell NSUserDefaults to save to disk now.
    defaults.synchronize()
}
let defaults = NSUserDefaults.standardUserDefaults()
//-----------------------------------------------------------------------------
//This code reads the singleton's properties from NSUserDefaults.
//edit this code to load your custom properties
someString = defaults.objectForKey(DefaultsKeys.someString) as! String?
someOtherString = defaults.objectForKey(DefaultsKeys.someOtherString) as! String?
someInt = defaults.objectForKey(DefaultsKeys.someInt) as! Int?
//-----------------------------------------------------------------------------
struct DefaultsKeys
{
  static let someString  = "someString"
  static let someOtherString  = "someOtherString"
  static let someInt  = "someInt"
}
DefaultsKeys.someInt
使用数据容器单例: 这个示例应用程序简单地使用了数据容器singleton

有两个视图控制器。第一个是UIViewController
ViewController
的自定义子类,第二个是UIViewController
SecondVC
的自定义子类

两个视图控制器上都有一个文本字段,并且都将数据容器singlelton的
someInt
属性中的值加载到其
viewwillbeen
方法中的文本字段中,并且都将文本字段中的当前值保存回数据容器的“someInt”中

将值加载到文本字段中的代码位于
视图中将出现:
方法:

override func viewWillAppear(animated: Bool)
{
  //Load the value "someInt" from our shared ata container singleton
  let value = DataContainerSingleton.sharedDataContainer.someInt ?? 0
  
  //Install the value into the text field.
  textField.text =  "\(value)"
}
将用户编辑的值保存回数据容器的代码位于视图控制器的
文本字段shouldenediting
方法中:

 func textFieldShouldEndEditing(textField: UITextField) -> Bool
 {
   //Save the changed value back to our data container singleton
   DataContainerSingleton.sharedDataContainer.someInt = textField.text!.toInt()
   return true
 }

您应该将值加载到用户界面的ViewWillDisplay中,而不是viewDidLoad中,这样每次显示视图控制器时,您的UI都会更新。

这个问题总是会出现

一个建议是创建一个数据容器singleton:一个在应用程序生命周期中只创建一次的对象,并在应用程序生命周期中保持不变

这种方法非常适用于需要在应用程序中的不同类之间提供/修改全局应用程序数据的情况

其他方法(如在视图控制器之间设置单向或双向链接)更适合在视图控制器之间直接传递信息/消息的情况

(其他备选方案见下文nhgrif的答案。)

使用数据容器singleton,可以向类中添加一个属性,该属性存储对singleton的引用,然后在需要访问时随时使用该属性

您可以设置singleton,使其将内容保存到磁盘,以便在两次启动之间保持应用程序状态

我在GitHub上创建了一个演示项目,演示了如何做到这一点。以下是链接:

以下是该项目的自述:

SwiftDataContainerSingleton 演示如何使用数据容器单例保存应用程序状态并在对象之间共享

DataContainerSingleton
类是实际的单例

它使用一个静态常量
sharedDataContainer
保存对singleton的引用

要访问singleton,请使用以下语法

DataContainerSingleton.sharedDataContainer
示例项目在数据容器中定义了3个属性:

  var someString: String?
  var someOtherString: String?
  var someInt: Int?
要从数据容器加载
someInt
属性,可以使用如下代码:

let theInt = DataContainerSingleton.sharedDataContainer.someInt
goToBackgroundObserver = NSNotificationCenter.defaultCenter().addObserverForName(
  UIApplicationDidEnterBackgroundNotification,
  object: nil,
  queue: nil)
  {
    (note: NSNotification!) -> Void in
    let defaults = NSUserDefaults.standardUserDefaults()
    //-----------------------------------------------------------------------------
    //This code saves the singleton's properties to NSUserDefaults.
    //edit this code to save your custom properties
    defaults.setObject( self.someString, forKey: DefaultsKeys.someString)
    defaults.setObject( self.someOtherString, forKey: DefaultsKeys.someOtherString)
    defaults.setObject( self.someInt, forKey: DefaultsKeys.someInt)
    //-----------------------------------------------------------------------------

    //Tell NSUserDefaults to save to disk now.
    defaults.synchronize()
}
let defaults = NSUserDefaults.standardUserDefaults()
//-----------------------------------------------------------------------------
//This code reads the singleton's properties from NSUserDefaults.
//edit this code to load your custom properties
someString = defaults.objectForKey(DefaultsKeys.someString) as! String?
someOtherString = defaults.objectForKey(DefaultsKeys.someOtherString) as! String?
someInt = defaults.objectForKey(DefaultsKeys.someInt) as! Int?
//-----------------------------------------------------------------------------
struct DefaultsKeys
{
  static let someString  = "someString"
  static let someOtherString  = "someOtherString"
  static let someInt  = "someInt"
}
DefaultsKeys.someInt
要将值保存到someInt,请使用以下语法:

DataContainerSingleton.sharedDataContainer.someInt = 3
DataContainerSingleton的
init
方法为
UIApplicationIdentinterBackgroundNotification
添加了一个观察者。该代码如下所示:

let theInt = DataContainerSingleton.sharedDataContainer.someInt
goToBackgroundObserver = NSNotificationCenter.defaultCenter().addObserverForName(
  UIApplicationDidEnterBackgroundNotification,
  object: nil,
  queue: nil)
  {
    (note: NSNotification!) -> Void in
    let defaults = NSUserDefaults.standardUserDefaults()
    //-----------------------------------------------------------------------------
    //This code saves the singleton's properties to NSUserDefaults.
    //edit this code to save your custom properties
    defaults.setObject( self.someString, forKey: DefaultsKeys.someString)
    defaults.setObject( self.someOtherString, forKey: DefaultsKeys.someOtherString)
    defaults.setObject( self.someInt, forKey: DefaultsKeys.someInt)
    //-----------------------------------------------------------------------------

    //Tell NSUserDefaults to save to disk now.
    defaults.synchronize()
}
let defaults = NSUserDefaults.standardUserDefaults()
//-----------------------------------------------------------------------------
//This code reads the singleton's properties from NSUserDefaults.
//edit this code to load your custom properties
someString = defaults.objectForKey(DefaultsKeys.someString) as! String?
someOtherString = defaults.objectForKey(DefaultsKeys.someOtherString) as! String?
someInt = defaults.objectForKey(DefaultsKeys.someInt) as! Int?
//-----------------------------------------------------------------------------
struct DefaultsKeys
{
  static let someString  = "someString"
  static let someOtherString  = "someOtherString"
  static let someInt  = "someInt"
}
DefaultsKeys.someInt
在观察者代码中,它将数据容器的属性保存到
NSUserDefaults
。您还可以使用
NSCoding
、核心数据或各种其他方法来保存状态数据。