Overview
I'm trying tot understand app groups so that I can pass data and variables from my main app to my extension and viceversa.
What I found
It's very hard for me to understand a few concepts because all I could find were other SO questions that only showed how to store and retrieve data.
I even watched this tutorial (and read some more on medium) but I'm still confused.
What I'm doing
First of all I enabled app groups both in my container app and my app extension and i set the app group name to group.grop
.
I have 3 files:
In my Shared.swift file I put the following code:
let sharedUserdefaults = UserDefaults(suiteName: SharedDefault.suitName)
struct SharedDefault {
static let suitName = "group.grop"
struct Keys{
static let letters = "letters"
}
}
Here the struct contains my suitName and the key.
Now, my keyboard extension looks like this:
in my keyboardViewController, over the view did load, I put the following code:
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!
inside of my 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)")
below my 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)
}
In my ViewController I have another button named dbutton, two labels and this code inside of my view controller:
guard let sharedWordss = sharedUserdefaults?.array(forKey: SharedDefault.Keys.letters) else {return}
print ("My words: \(sharedWordss)")
Now what I want to happen is:
But using this method I can't access the lept
variable from my ViewController. So I can't add anything to the array and I can't call lept.count, for example.
Question
How do I access (get the value/ add items/ edit...) a variable from a target in another target?
If you have anything I could use to take a better look into the subject, please send me the links!
lept
to be a getter, and always get the latest value from the sharedDefaults
:var lept: [Int] {
return sharedUserdefaults?.array(forKey: SharedDefault.Keys.letters) as? [Int] ?? [Int]()
}
Inside the viewDidLoad
for your keyboard extension, remove the code which saves the lept
array to the sharedDefaults
:
sharedUserdefaults?.set(lept, forKey: SharedDefault.Keys.letters)
Create a function which will do the same thing for each button (below I will write some optimizations regarding all this code):
func appendValue() {
var currentLept = self.lept
currentLept.append(1)
sharedUserdefaults?.set(currentLept, forKey: SharedDefault.Keys.letters)
//print(currentLept) - you can print for debug purposes
}
@IBAction func aaction(_ sender: Any) {
appendValue()
}
This is the basic logic for sending any data from the main target
to an extension
.
Optimization hints
You should consider using a UICollectionView
which will hold all your labels and buttons, and each cell would act as a button or label in your scenario. This way, you will create a custom UICollectionViewCell and implement everything just once, instead of handling each button separately.
As a rule of thumb, if you have anything which is repeating at least twice, it is either a tableView, if you need just vertical scrolling, or it should be a collectionView if you need horizontal scrolling, or cells which occupy only a portion of the screen's width.