Reputation: 135
i am trying to dynamically create UIButtons inside UIStackViews that will load into a TableViewCell.
i have two arrays that hold String values:
array_1 = ["a" , "b" , "c"]
array_2 = ["x" , "y" , "z"]
i have a function that creates a UIButton, and a function that generates an array of UIButton arrays that holds one value from 'array_1' plus all the values from 'array_2' (i.e: [[a,x,y,z], [b,x,y,z], [c,x,y,z]])
func createButton(title : String) -> UIButton {
let newButton = UIButton(type: .system)
newButton.setTitle(title, for: .normal)
newButton.backgroundColor = UIColor.lightGray
return newButton
}
func generateButtons() -> [[UIButton]]{
var topButtonArray = [UIButton]()
var buttomButtonArray = [UIButton]()
var finalButtonArray = [[UIButton]]()
for title in array_1 {
topButtonArray += [createButton(title: title)]
}
for title in array_2 {
buttomButtonArray += [createButton(title: title)]
}
for button in topButtonArray {
finalButtonArray += [[button]+buttomButtonArray]
}
return finalButtonArray
}
now i have a function that creates a UIStackView which its arranged subviews are the button arrays, and one that generates an array of UIStackViews that hold those stackViews with buttons
func createStackView(subViews : [UIButton]) -> UIStackView{
let stackView = UIStackView(arrangedSubviews: subViews)
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.alignment = .fill
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.spacing = 5
return stackView
}
func generateStackViewArray() -> [UIStackView] {
var stackViewArray = [UIStackView]()
let finalButtonArray = generateButtons()
for buttons in finalButtonArray{
stackViewArray += [createStackView(subViews: buttons)]
}
return stackViewArray
}
finally, i want to load those UIStackViews into individual UITableViewCells
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array_1.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "First")!
cell.contentView.addSubview(generateStackViewArray([indexPath.row])
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let screenSize : CGRect = UIScreen.main.bounds
let screenHeight = screenSize.height
let relativeCellSizeDefault = screenHeight / CGFloat (array_1.count)
return relativeCellSizeDefault
}
right now my final result is a UITableView, with 3 cells (just as i want) but in the first and second cell i can only see the first button (i.e : a/ b) but in the third cell i get what i want to happen (i.e: a,x,y,z):
i tried figuring out the problem with my logic but i can't seem to find the answer why it only loads the entire button array in the last cell.
also, i am a beginner so there might be some redundancy or i might not be using best practice for some stuff - feel free to correct me and thank you very much for helping
Upvotes: 1
Views: 623
Reputation: 15321
Classes in swift are pass by reference not pass by value. UIButton
is a class. The way your code is written currently you are only creating one instance of button "a", button "b", and button "c". But those instances have been added to multiple arrays which are then used to populate multiple stack views. So button "a" is added to stack view "x", but then is added to stack view "y", when this happens it is removed from stack view "x" because a UIView
can only have one super view at a time. This happens again when it is added to stack view "z". You need to change your code so you are instantiating new instances for of the "a", "b", and "c" buttons for each cell. Something like:
func generateButtons() -> [[UIButton]]
{
var topButtonArray = [UIButton]()
var finalButtonArray = [[UIButton]]()
for title in array_1
{
topButtonArray.append(createButton(title: title))
}
for button in topButtonArray
{
var buttonArray = [UIButton]()
buttonArray.append(button)
for title in array_2
{
buttonArray.append(createButton(title: title))
}
finalButtonArray.append(buttonArray)
}
return finalButtonArray
}
Upvotes: 1