UITextField - Limit text lenght not by character count - xcode

is there a way to limit a textfield but not by character count? I would like to stop the ability to type when the end of the field is reached. But as different characters have different dimensions stopping at a certain count ist not really a solution. Something like "stop at the end of the line" would be perfect.
this doesn't work for me
Max length UITextField

What you want to do is instead of calculating the maximum number of characters of the new string, calculate it's width in points and compare it to the width you need.
[Swift]
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let combinedString = textField.attributedText!.mutableCopy() as NSMutableAttributedString
combinedString.replaceCharactersInRange(range, withString: string)
return combinedString.size().width > textField.bounds.size.width
}
You might need to edit the attributes to get it to render on a single line.

Subscribe to controlTextDidChange and calculate the size of the text via
let s = NSString(string: <yourtext>)
let size = s.boundingRectWithSize(<#size: NSSize#>, options: <#NSStringDrawingOptions#>, attributes: <#[NSObject : AnyObject]?#>)
Now you can check if the text is too large.

Related

Make UITextField with VoiceOver read numbers as digits

Our App has a few UITextField where users enter alphanumeric input codes such as "AA149873A".
We'd like voice over to read these as "A A 1 4 9 8 7 2 A", but it instead reads the digits as a number: "One hundred and forty nine thousand, eight hundred and seventy three".
Is there some way to configure UITextField so that it knows its content shouldn't be thought of as numbers, but individual digits?
Thanks.
We'd like voice over to read these as "A A 1 4 9 8 7 2 A", but it instead reads the digits as a number: "One hundred and forty nine thousand, eight hundred and seventy three".
The fastest wy to reach your goal is to add spaces between each character in the accessibilityValue of the UITextField as follows: 🤓
class AccessibilityTextField: UITextField {
var _str: String?
override var text: String? {
get { return _str}
set {
_str = newValue!
accessibilityValue = _str!.map{String($0)}.joined(separator: " ")
}
}
convenience init() { self.init() }
required init?(coder: NSCoder) { super.init(coder: coder) }
}
I didn't implement all the text field delegate stuff to test it ⟹ I created a blank project only with an UITextField adding a "BB0024FG" plain text and changed the text in the viewDidAppear of my view controller:
myTextField.text = "AA14987A"
In the end, VoiceOver spells out each character after another without reading out the initial plain text. 👍
Following this rationale, you have a way that let VoiceOver know that the UITextField content must be thought as individual digits. 😉
As of iOS 13 it is possible to add a string attribute to direct voice-over vocalisation to spell strings out as individual letters and digits.
I've not found a way to direct UITextField to add this attribute to its content. However, a UITextField subclass can override it's accessibilityValue to achieve this.
The subclass given here adds a property to enable or disable this behaviour.
final class AccessibilityTextField: UITextField {
var isAlphanumeric: Bool = false
override public var accessibilityAttributedValue: NSAttributedString? {
get {
guard let text = text, !text.isEmpty else {
return nil
}
return NSAttributedString(string: text, attributes: valueAttributes)
}
set {
// Ignore these values.
_ = newValue
}
}
private var valueAttributes: [NSAttributedString.Key: Any] {
guard #available(iOS 13.0, *), isAlphanumeric else {
return [:]
}
return [.accessibilitySpeechSpellOut: true]
}
}
An alternative approach is given in another answer here that doesn't use the iOS 13 feature . accessibilitySpeechSpellOut. However, I've seen it suggested that this is not ideal for brail output systems as they also use accessibilityLabel. Perhaps this is a good fallback on pre iOS 13 systems.

Set Limit for TextField characters in RxSwift [duplicate]

This question already has an answer here:
RxSwift/RxCocoa: prevent UITextField from having more than ... characters
(1 answer)
Closed 4 years ago.
I want to set a limit for characters in a textFiled using RxSwift,
may be i can benefit from Scan operator but i don't know how to use it in this case ,
I want my resulting code to behave as same as implementing it in shouldChangeCharacterInRage method:
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String)
-> Bool {
if textField == baseTextFiled{
let enteredString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
if enteredString.count > limit{ // limit defined previously
return false
}
}
return true
}
Any help?
ReactiveX pushes data, so isn't really compatible with that particular delegate method. That said, you can still do it because .rx.text is a control property...
baseTextField.rx.text.orEmpty // pushes text
.map { String($0.prefix(limit)) } // pushes first X characters in text
.distinctUntilChanged() // only pushes if text is different than previously
.bind(to: baseTextField.rx.text) // pushes text into text field
.disposed(by: bag)

Adding different alignment and font size to different lines in one TextLabel in TableCell swift

so i'm trying to implement a simple english to farsi dictionary in iOS
i'd like to include both words in one table cell, problem is that english is L>R and farsi is R>L, also i'd like to make the farsi word a bit bigger.
I created an AttributedMutableString and I thought I put down all the correct values but it looks like there is a problem since it isn't rendering correctly.
code:
cell.textLabel?.numberOfLines = 0
var myString = "\(englishConvo[indexPath.row])\n\(farsiConvo[indexPath.row])"
var mutableString = NSMutableAttributedString()
var lenOfLang1 = englishConvo[indexPath.row].characters.count
var lenOfLang2 = farsiConvo[indexPath.row].characters.count
let increaseFontSize = UIFont(name: (cell.textLabel?.font.fontName)!, size: (cell.textLabel?.font?.pointSize)! + 5)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.Right
mutableString = NSMutableAttributedString(string: myString)
mutableString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSRange(location: lenOfLang1 + 1, length: lenOfLang2))
mutableString.addAttribute(NSFontAttributeName, value: increaseFontSize!, range: NSRange(location: lenOfLang1 + 1, length: lenOfLang2))
cell.textLabel?.attributedText = mutableString
If i convert to a string using this code this is what I get
cell.textLabel?.text = String(mutableString)
Any thoughts / ideas would be super appreciated
Table cells already come with a layout that gives you two labels (text and detail), so why not just use it? Here, for example, in a language app of mine, I'm displaying a Latin word in the text label and an English translation in the detail label. You could easily do the same with Farsi and English.

How do I limit NSTextView to 2 lines?

I'm trying to specify the number of lines for NSTextView. My designer is requesting 2 lines of text max. I've tried NSMutableParagraph style to add the ellipses truncation that I want, but with NSMutableParagraph I can only get NSTextView with 1 line and without NSMutableParagraph, I get a scrolling text with as many lines as needed to complete text.
var attributedString = NSMutableAttributedString(string: "This is my text, I can keep going for many characters")
var para = NSMutableParagraphStyle()
para.lineBreakMode = NSLineBreakMode.ByTruncatingTail
let globalAttributes = [
NSParagraphStyleAttributeName: para
]
let range = NSRange(location:0, length: attributedString.length)
attributedString.addAttributes(globalAttributes, range: range)
cellView.myTextView!.textStorage?.setAttributedString(attributedString)
I've tried height constraint on NSTextView. I've tried:
cellView.myTextView!.textContainer?.containerSize = NSMakeSize(300, 32)
I've tried creating IBOutlet for NSScrollView that NSTextView in within and adjusting its height. No luck with getting both 2 lines and truncation. Any help is greatly appreciated. I feel like I'm just missing a method or setup. Thanks!
From 10.11 you can use this
yourTextViewObj.textContainer.maximumNumberOfLines = 2;
You can use an NSTextField configured as a multi-line label. That means setting its cell's wraps property to true and, if desired, its truncatesLastVisibleLine to true.
For NSTextField (aka label) You can just do self.textField.maximumNumberOfLines = 2;
That's it.
Max number of lines is now a property of NSTextField
label.maximumNumberOfLines = 1;

adding numbers in uitextfield to update uilabel

I have code with several uitextfields that will be used to input numbers, and I want to add these numbers together to update a uilabel.
I can do all the updating and the labels and fields, but can't get the addition to work.
Just now I have:
label.text = (textfield1.text + textfield2.text);
I assume I need to convert these textfield inputs to an int, but not sure how to do that...
there is a couple of extra steps you have to do:
convert the string value of your text filed into numerical value
do the math there
and convert it back.
For example (i use float in my case, you can change that to whatever type you want):
float textField1Value = [textfield1.text floarValue];
float textField2Value = [textfield2.text floarValue];
label.text = [NSString stringWithFormat:#"%f", textField1Value + textField2Value];
Hope that helps.

Resources