在目标之间传递数据和变量

Passing data and variables between targets

概览
我正在尝试了解应用程序组,以便我可以将数据和变量从我的主应用程序传递到我的扩展程序,反之亦然。

我发现了什么
我很难理解一些概念,因为我只能找到其他 SO 问题,这些问题仅展示了如何存储和检索数据。
我什至看了 this 教程(并在媒体上阅读了更多内容),但我仍然感到困惑。

我在做什么
首先,我在我的容器应用程序和我的应用程序扩展中启用了应用程序组,并将应用程序组名称设置为 group.grop

我有 3 个文件:

  1. Shared.swift
  2. 键盘ViewController
  3. ViewController

在我的 Shared.swift 文件中,我输入了以下代码:

let sharedUserdefaults = UserDefaults(suiteName: SharedDefault.suitName)
struct SharedDefault {
    static let suitName = "group.grop"
    struct Keys{
        static let letters = "letters"
    }
}

这里的结构包含我的 suitName 和密钥。

现在,我的键盘扩展如下所示:

在我的键盘 ViewController 中,在视图确实加载后,我输入了以下代码:

    var lept: [Int] = sharedUserdefaults?.array(forKey: SharedDefault.Keys.letters) ?? []
    
    @IBOutlet weak var alabel: UILabel!
    @IBOutlet weak var blabel: UILabel!
    @IBOutlet weak var clabel: UILabel!
    
    @IBOutlet weak var abtn: UIButton!
    @IBOutlet weak var bbtn: UIButton!
    @IBOutlet weak var cbtn: UIButton!

在我的 viewDidLoad 里面:

let nib = UINib(nibName: "keygrop", bundle: nil)
              let objects = nib.instantiate(withOwner: self, options: nil)
              view = objects[0] as? UIView

        
        sharedUserdefaults?.set(lept, forKey: SharedDefault.Keys.letters)
        guard let sharedWords = sharedUserdefaults?.array(forKey: SharedDefault.Keys.letters) else {return}
        print ("My words: \(sharedWords)")

在我的 viewDidLoad 下方:

//I have one of these for every button.
 @IBAction func aaction(_ sender: Any) {
        
       lept.append(1)
        sharedUserdefaults?.set(lept, forKey: SharedDefault.Keys.letters)
       print(lept)
    }

在我的 ViewController 中,我有另一个名为 dbutton 的按钮、两个标签和我的视图控制器中的这段代码:

 guard let sharedWordss = sharedUserdefaults?.array(forKey: SharedDefault.Keys.letters) else {return}
        
        print ("My words: \(sharedWordss)")

现在我想要发生的是:

  1. 用户按下键盘上的按钮。
  2. 一个数字存储在一个数组中。
  3. 用户打开应用程序,如果他按下 d 按钮,另一个值将存储在数组中。
  4. 一个标签显示数组中的内容,另一个标签显示数组中元素的数量。

但是使用这种方法我无法从 ViewController 访问 lept 变量。所以我无法向数组添加任何内容,也无法调用 lept.count,例如。

问题
我如何访问(获取值/添加项目/编辑...)来自另一个目标中的目标的变量?
如果您有任何我可以用来更好地研究该主题的信息,请将链接发送给我!

  1. 将您的 lept 修改为 getter,并始终从 sharedDefaults:
  2. 获取最新值
var lept: [Int] {
    return sharedUserdefaults?.array(forKey: SharedDefault.Keys.letters) as? [Int] ?? [Int]()
}
  1. 在键盘扩展的 viewDidLoad 中,删除将 lept 数组保存到 sharedDefaults:

    的代码

    sharedUserdefaults?.set(lept, forKey: SharedDefault.Keys.letters)

  2. 创建一个函数,为每个按钮做同样的事情(下面我将写一些关于所有这些代码的优化):

func appendValue() {  
    var currentLept = self.lept
    currentLept.append(1)
    sharedUserdefaults?.set(currentLept, forKey: SharedDefault.Keys.letters)
   //print(currentLept) - you can print for debug purposes
}
  1. 每次按下按钮时调用该函数:
@IBAction func aaction(_ sender: Any) {
        
   appendValue()
}

这是将任何数据从 main target 发送到 extension 的基本逻辑。

优化提示

您应该考虑使用 UICollectionView 来保存所有标签和按钮,并且每个单元格在您的场景中充当按钮或标签。这样,您将创建一个自定义的 UICollectionViewCell 并仅实现所有内容一次,而不是分别处理每个按钮。

根据经验,如果你有任何东西至少重复两次,它要么是一个 tableView,如果你只需要垂直滚动,或者它应该是一个 collectionView,如果你需要水平滚动,或者单元格只占屏幕宽度的一部分。