How to access UILabel without IBOutlets. Swift - ios

I want to change the backgroundColor for several labels without using an outlet.
If i set tag for UILabel i can this
let label = self.darkView.viewWithTag(1) as? UILabel
label?.backgroundColor = UIColor.black
But I want to do this for multiple objects and without a tag. I tried this but it doesn't work
if let labels = self.darkView.subviews as? [UILabel] {
for label in labels {
label.backgroundColor = UIColor.black
}
}
How i can implemented this ?

You can iterate through all subViews of your custom view and check for each label like this:
for view in self.darkView.subviews as [UILabel] {
if let label = view as? UILabel {
label.backgroundColor = UIColor.black
}
}

Related

How do I change the attributes of a UILabel with a custom programmatic UIView [Swift 5]

I'm designing a UI in Swift 5 programatically. Within the superview, I've added a subview called viewLeft1 with the type UIStackView. Inside viewLeft1's declaration, I've created a UILabel with some default attributes.
The declaration of viewLeft1
let viewLeft1: UIStackView = {
let stackView = UIStackView()
let lbl = UILabel()
stackView.addSubview(lbl)
lbl.text = "--"
return stackView
}()
An example of a function that would change the text attribute of lbl
func updateLabel1() {
// Change the lbl.text to "302"
}
The problem is that I don't know how to access lbl because it was defined within viewLeft1.
How could I achieve this? Any help is appreciated! Thanks.
I would rather add another property for the label:
let label: UILabel = {
let lbl = UILabel()
lbl.text = "--"
return lbl
}()
let viewLeft1: UIStackView = {
let stackView = UIStackView()
// configure other properties of stackView, such as constraints,
// but don't add viewLeft1 to it here
return stackView
}()
And then in the initialiser of the view, where you add viewLeft1 to self, also add label to viewLeft1:
self.addSubview(viewLeft1)
viewLeft1.addArrangedSubview(label)

Swift: Programmatically add multiple stack view one below the other through a loop

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.
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!

Customizing SLComposeSheetConfigurationItem

I want to customize SLComposeSheetConfigurationItem
I am looking to change the font and color for its title and value
There does not seem to be any documentation for this but several apps like Evernote have done that.
SLComposeSheetConfigurationItem's contents are loaded in tableView, so you can't directly access both label. You need to first get tableView by accessing hierarchy of views and then access visibleCells from table view. there are only one cell, so access subViews of contentView of first cell which will give you two label.
So, first one label is left hand side and second one at right hand side. Change its font size, color, title as we are doing in normal label and reload data.
See following code.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let slSheet = self.children.first as? UINavigationController {
// Change color of Cancel and Post Button
slSheet.navigationBar.tintColor = .orange
// All contents of botton view are loaded inside table view at specific level of child view
if let tblView = slSheet.children.first?.view.subviews.first as? UITableView,
let firstCell = tblView.visibleCells.first
{
// Enumerate on subViews of contentView
for (index, label) in firstCell.contentView.subviews.enumerated() {
if index == 0 {
// Left label
if let lblLeft = label as? UILabel {
lblLeft.font = UIFont(name: "Helvetica-Bold", size: 20)
lblLeft.textColor = .orange
}
} else {
// Right label
if let lblRight = label as? UILabel {
lblRight.font = UIFont(name: "Helvetica", size: 14)
lblRight.textColor = .green
}
}
}
// Reload table if label not loading properly
tblView.reloadData()
}
}
}
Output:

Iterate through all labels in a static table view

I have a static tableViews and a button to change the colour scheme (theme) of the app. Is there a fast way for me to change all the label colours throughout the table from white to black?
im thinking something like the following.
Pseudo code:
for subview in view.subviews {
if subview is UILabel {
subview.fontColor = .black
}
}
So when the orange switch is on the "Light" side I would like all labels to go black. I have used story board to construct it, so it would be nice if I could avoid having to connect all labels to the .swift file.
I am writing about code for your sudo code you need to iterate with recursion.
func getLabelsInView(view: UIView) -> [UILabel] {
var results = [UILabel]()
for subview in view.subviews as [UIView] {
if let label = subview as? UILabel {
results += [label]
} else {
results += getLabelsInView(view: subview)
}
}
return results
}
Call any where from you need to change color
let labels = getLabelsInView(self.view) // or any other view / table view
for label in labels {
label.textColor = .black
}

Fix width of element in UIStackView

I create UIStackViews programmatically and add them to parent UIStackView, which is created in Storyboard. Child stack views are horizontal with 2 labels. I need to fix width of second UILabel and make the first UILabel fill the rest space.
Now I have this:
And I want this:
My code for generating children stack views:
#IBOutlet weak var parentStackView: UIStackView!
func addStackViewsToParentStackView(params: [String: Float]) {
for (name, value) in params {
let parameterNameLabel = UILabel() // first label
parameterNameLabel.text = name
let parameterValueLabel = UILabel() // second label
parameterValueLabel.text = value.description
parameterValueLabel.frame.size.width = 80.0 // I've tried to fix width, but it does't help
let childStackView = UIStackView(arrangedSubviews: [parameterNameLabel, parameterValueLabel])
childStackView.axis = .Horizontal
childStackView.distribution = .FillProportionally
childStackView.alignment = .Fill
childStackView.spacing = 5
childStackView.translatesAutoresizingMaskIntoConstraints = true
parentStackView.addArrangedSubview(childStackView)
}
}
Thanks for any help!
Just put width constraints on the labels.
parameterValueLabel.widthAnchor.constraint(equalToConstant: 80).isActive = true

Resources