UITextField to change size to fix text content - swift

I have a custom UITableViewCell with a UITextField. I have the cell in a tableview inside my view controller.
let cellText : UITextField = {
let secureText = UITextField()
secureText.isSecureTextEntry = true
secureText.isUserInteractionEnabled = false
return secureText
}()
I want to change the size of the textField based on the amount of text that is inside the text field.
note* I do need the this to be a UITextField field because I want the text to go through as a isSecure text.

try this (when you're done editing):
textField.frame.size.width = textField.intrinsicContentSize.width

Related

Swift: programmatically locate a UITextFelds UILabel and containing UIView container

I have a form with a UIView wrapping around a UILabel and UITextField. When a user enters the field I would like to change the colour of the label and the border colour of the view container.
If I call a function on the firstResponder I will need to find the text field's corresponding label and view copntainer.
I thought to have a firstResonder function for each field and in each function send the corresponding outlets (textfield, label, view) to a function which handles the colour changes for the label and view border.
This is not terrible but I and sure this can be accomplished more efficiently.
Any pointers please.
edit:
I changed my requirement slightly to place the label inside the textfield and highlight the textfield border instead of the encapsulating view.
This is what I ended up with:
override func viewDidLoad() {
super.viewDidLoad()
firstNameLabel.connect(with: firstName)
}
extension UILabel {
#objc
func editingChanged(textField: UITextField) {
}
#objc
func editingDidBegin(textField: UITextField) {
self.textColor = UIColor.blue
textField.layer.borderColor = UIColor.blue.cgColor
}
#objc
func editingDidEnd(textField: UITextField) {
self.textColor = UIColor.green
textField.layer.borderColor = UIColor.green.cgColor
}
func connect(with textField:UITextField){
//textField.addTarget(self, action: #selector(UILabel.editingChanged(textField:)), for: .editingChanged)
textField.addTarget(self, action: #selector(UILabel.editingDidBegin(textField:)), for: .editingDidBegin)
textField.addTarget(self, action: #selector(UILabel.editingDidEnd(textField:)), for: .editingDidEnd)
textField.layer.borderColor = UIColor.gray.cgColor
textField.layer.borderWidth = 1;
textField.layer.cornerRadius=10
}
}
The usual thing is to give each member of each group a corresponding tag. Since viewWithTag drills down to find any view with the given tag, the problem is solved if you know how to convert the tag value of the view you have to the tag value of the view you want.
For example, text field 10, view 110, label 210; text field 11, view 111, label 211; and so on. Or whatever system suits your fancy.
Alternatively just walk the view hierarchy. The view is the text field's superview, and the label is the first subview of the view that is a label.

UICollectionViewListCell Accessory TopTrailing Placement

iOS 14 introduced a bunch of advancements for UICollectionView including the new UICollectionViewListCell. Using the defaultContentConfiguration, you can add accessory views to the cell. I'm looking to recreate an iMessage conversation row (mail is also close) where the date label is in the top trailing corner. Is there anyway to do this using the default configuration? Having to create a custom cell seems like overkill just for this.
Here is what I currently have.
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Int> { cell, indexPath, item in
var content = cell.defaultContentConfiguration()
content.text = "Title"
content.secondaryText = "This is the body of the message and it's really long. I want to see where it finally truncates because thats what it should do eventually you know?"
content.secondaryTextProperties.numberOfLines = 2
content.image = UIImage(systemName: "star")
let label = UILabel()
label.text = "4/26/7"
label.textColor = .secondaryLabel
label.font = .preferredFont(forTextStyle: .caption1)
let customAccessory = UICellAccessory.CustomViewConfiguration(
customView: label,
placement: .trailing(displayed: .always))
cell.accessories = [.customView(configuration: customAccessory)]
cell.contentConfiguration = content
cell.tintColor = .tertiaryLabel
}
Here is my desired result
Here is mail for another example
The default UICollectionViewListCell has limited customization possibilities.
Your best shot is with a custom UICollectionViewCell subclass. You will instead have the cell registration register your custom class, and dequeue cells the same way you would dequeue a built-in UICollectionViewListCell class object.

Swift - Custom cell width and height for textlabel and detailTextLabel

I wanna manage the long text in textlabel and detailtextlabel for the cells in UITableview because if the textlabel has a long text the detailedtextlabel truncate with "..." and viceversa.
Here's the problem:
So I wanna know if there's a way to manage the space between textlabel and detailtextlabel so there's no truncate and give them more lines. I tried with:
...
if tableData[indexPath.row].clave.count > 6 {
cell?.detailTextLabel?.numberOfLines = 5
cell?.textLabel?.numberOfLines = 5
} else {
cell?.detailTextLabel?.numberOfLines = 1
}
cell?.textLabel?.text = nueva_cadena_string
cell?.detailTextLabel?.text = tableData[indexPath.row].clave
cell?.textLabel?.textColor = UIColor.brown
cell?.textLabel?.font = UIFont.boldSystemFont(ofSize: 15.0)
cell?.textLabel?.lineBreakMode = .byWordWrapping
return cell!;
But it doesn't work very well, it seems to give them just 2 lines, not 5 and I can't change the width for the textlabel and detailtextlabel.
Try making your cell custom as this:
Try setting the tableviews row dimension to automatic
yourTableView.rowHeight = UITableViewAutomaticDimension
yourTableView.estimatedRowHeight = 80.0
try setting both textlabels number of lines either in the storyboard or in code to 0 as then they will all have the amount of lines they need.
You can subclass UITableViewCell and override the layoutSubviews() method. You will need to change the layout of textLabel and detailTextLabel there. Remember that these elements lie inside contentView, not in the cell itself.
But better you add two custom labels on the Storyboard and configure them as you want. It's easier.

Variable name in a loop using an integer

I want to change the text of a lot of labels. All my labels are named LabelName1, LabelName2, LabelName3.
How can I edit my labels with one loop like this:
for i in 1..10 {
LabelName(i).Text = String(some text, the some for each label)
}
You should store all of your UILabels in an array and change the text for all of them like this:
for label in labelArray {
label.text = String(some text, the some for each label)
}
Alternatively to #toddg fine answer, you could assign a specific tag to the labels and loop through the subviews:
// loop through subviews and update all UILabels with a tag property of 4
for view in self.subviews as [UIView] {
if let label = view as? UILabel {
if label.tag == 4 {
label.text = String(some text, the some for each label)
}
}
}
The advantages to this is no arrays are needed, and you can be as specific or generic as desired.

UITextField with a placeholder containing an image and text

is there any way I could have a magnifier icon stuck to my placeholder in a UITextField like the below:
I tried to override leftViewRectForBounds(bounds: CGRect):
override func leftViewRectForBounds(bounds: CGRect) -> CGRect {
var superRect = super.leftViewRectForBounds(bounds)
superRect.origin.x += 80
return superRect
}
but it didn't work
You can add images to text using NSAttributedString and NSTextAttachment.
I haven't used them in a while but I believe you can do something like this...
let magnifyingGlassAttachment = NSTextAttachment(data: nil, ofType: nil)
magnifyingGlassAttachment.image = UIImage(named: "MagnifyingGlass")
let magnifyingGlassString = NSAttributedString(attachment: magnifyingGlassAttachment)
now you can use the magnifyingGlassString attributed string and add it as part of the attributed text to the UITextField.
I believe you can also specify exactly how the magnifying glass renders alongside the string (how it wraps etc...)
Something like this...
var attributedText = NSMutableAttributedString(attributedString: magnifyingGlassString)
let searchString = NSAttributedString(string: "Search for stuff")
attributedText.appendAttributedString(searchString)
textField.attributedPlaceholder = attributedText
You can add a image view or a custom view that displays this icon over the text field by properly placing it over and set up appropriate layout constraints. You will be adding this view as a sibling and not subview though.