Reputation: 544
I have a view controller created in the storyboard and the it contains (check image for reference)
ScrollerView
a. StackViewA (image: green)
i. LabelA
ii. LabelB
b. StackViewB (image: green)
i. LabelC
ii. LabelD
I am fetching data from the API and am able to show that data in those labels.
Now, the 3rd set of data that I am fetching is dynamic, meaning it can be 2 more StackView (image: red) under the second StackView or 3 more etc. I am guessing that I have the add that StackView programmatically in the controller inside the loop so that is created according to the loop.
Currently my 3rd StackView is also created in the storyboard and therefore it is showing only the last data from 3rd set after looping through them.
How do I solve that?
More specifically:
How can I add a StackView inside the ScrollerView created in the storyboard.
How do I contains it to position itself below the 2nd StackView also created in the storyboard.
Update
class InfoDetailsViewController: UIViewController {
// MARK: - Outlets
@IBOutlet weak var infoStack: UIStackView!
@IBOutlet weak var mainScroll: UIScrollView!
static var apiResp: APIDetailsResponse.APIReturn?
let infos: [APIDetailsResponse.Info] = (APIDetailsViewController.apiResp?.content?.infos)!
override func viewDidLoad() {
super.viewDidLoad()
infoStack.spacing = 25.0
for info in infos {
let addInfoTitle = UILabel()
addInfoTitle.font = .preferredFont(forTextStyle: .body)
addInfoTitle.backgroundColor = .orange
addInfoTitle.translatesAutoresizingMaskIntoConstraints = false
let addInfoContent = UITextView()
addInfoContent.font = .preferredFont(forTextStyle: .body)
addInfoContent.backgroundColor = .green
addInfoContent.translatesAutoresizingMaskIntoConstraints = false
addInfoTitle.text = "\(String(describing: (info.info_title)!))"
let htmlString = "\(String(describing: (info.information)!))"
// works even without <html><body> </body></html> tags, BTW
let data = htmlString.data(using: String.Encoding.unicode)!
let attrStr = try? NSAttributedString(
data: data,
options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html],
documentAttributes: nil)
addInfoContent.attributedText = attrStr
let childStackView = UIStackView(arrangedSubviews: [addInfoTitle, addInfoContent])
childStackView.alignment = .fill
childStackView.axis = .vertical
childStackView.distribution = .fill
childStackView.spacing = 5.0
childStackView.translatesAutoresizingMaskIntoConstraints = false
infoStack.addArrangedSubview(childStackView)
}
}
Currently I have this. What is happening now is no matter how many data the array is returning, I am always getting title and content for the first one and only title for each consecutive data.
Upvotes: 0
Views: 6497
Reputation: 1002
So the best solution is when you create your scrollview add a stack view inside it. And whenever you are creating stack view dynamically add under that stack view which is inside scrollview. So in this case you new stack view will gets stacked under your outer stack view in proper manner.
ScrollView -> 1 Stackview -> Multiple Dynamic stack views in loop
lets say you already have stack view named ParentStackview from your storyboard. Then follow these steps
lazy var childStackView: UIStackView = {
let stackView = UIStackView()
stackView.alignment = .center
stackView.axis = .vertical
stackView.distribution = .equalCentering
stackView.spacing = 30.0
return stackView
}()
public func viewDidLoad() {
ParentStackview.alignment = .center
ParentStackview.axis = .vertical
ParentStackview.distribution = .equalCentering
ParentStackview.spacing = 10.0
for eachChild in data {
ParentStackView.addArrangedSubview(childStackView)
childStackView.translatesAutoresizingMaskIntoConstraints = false
childStackView.widthAnchor.constraint(equalTo: securityScrollView.widthAnchor)
//set height too
// this below function you can use to add eachChild data to you child stackview
configureStackview(childstackView, eachChild)
}
}
Enjoy!
Upvotes: 2