How to make text typed in TextField undeletable?
The idea is the create UITextField class and use UIViewRepresentable to bind with SwiftUI view. By this, you can use all delegate methods and detect backspace. Also, using this you can prevent from cut and delete from tap action.
UndeletableTextField custom class
class UndeletableTextField: UITextField {
// This for prevent to cut and delete
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(UIResponderStandardEditActions.delete(_:)) ||
action == #selector(UIResponderStandardEditActions.cut(_:)) {
return false
}
return super.canPerformAction(action, withSender: sender)
}
}
UIViewRepresentable view
struct UndeletableTextFieldUI: UIViewRepresentable {
@Binding var text: String
var placeholder: String
func makeUIView(context: Context) -> UndeletableTextField {
let textField = UndeletableTextField(frame: .zero)
textField.delegate = context.coordinator
textField.placeholder = placeholder
return textField
}
func updateUIView(_ uiView: UndeletableTextField, context: Context) {
uiView.text = text
}
func makeCoordinator() -> Coordinator {
Coordinator(parent: self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: UndeletableTextFieldUI
init(parent: UndeletableTextFieldUI) {
self.parent = parent
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Here we detect backspace and ignore it.
if let char = string.cString(using: String.Encoding.utf8) {
let isBackSpace = strcmp(char, "\\b")
if (isBackSpace == -92) {
print("Backspace was pressed")
return false
}
}
return true
}
}
}
ContentView
struct ContentView: View {
@State private var text: String = ""
var body: some View {
UndeletableTextFieldUI(text: $text, placeholder: "Type here")
}
}
Make portion of UITextView undeletable
sch's last edit makes a decent answer, but I want to offer a slightly more flexible approach.
You have to keep in mind the copy/paste system. User might select all the text in text field and try to paste in the entire value which might be perfectly acceptable, but if (range.location <= 9) { return NO; }
will reject it. The way I'd do it is put together a string that would be a result of successful edit and then check if that string would start with your desired prefix.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *resultString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSLog(@"resulting string would be: %@", resultString);
NSString *prefixString = @"blabla";
NSRange prefixStringRange = [resultString rangeOfString:prefixString];
if (prefixStringRange.location == 0) {
// prefix found at the beginning of result string
return YES;
}
return NO;
}
Edit: if you want to check if the current string in text field starts with the prefix, you can use rangeOfString:
the same way:
NSRange prefixRange = [textField.text rangeOfString:prefixString];
if (prefixRange.location == 0) {
// prefix found at the beginning of text field
}
Adding text to UITextField you can't delete
You can implement this code in shouldChangeCharactersInRange
delegate method.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField.text.length == 1 && [string isEqualToString:@""]) {//When detect backspace when have one character.
textField.text = @"myText";
}
return YES;
}
Swift: Limit Characters # in textField without disabling/interfering with other functions
You're being given the textField
that is changing characters in the delegate function. Here, you can compare it to the specific fields that you want to limit:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else { return true }
if !(textField == stuffOneTextField || textField == descriptionTextField) {
return true
}
let newLength = text.characters.count + string.characters.count - range.length
return newLength <= limitLength
}
Also, func textFieldShouldReturn(textField: UITextField!) -> Bool
is giving you a text field, and you can call resignFirstResponder()
on that, if that is what you want to do there.
How do I make a text input non-editable?
<input type="text" value="3" class="field left" readonly>
No styling necessary.
See <input>
on MDN https://developer.mozilla.org/en/docs/Web/HTML/Element/input#Attributes
Uneditable prefix inside a UITextField using Swift
For the first part, you can refactor your delegate method as follow.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
//This makes the new text black.
textField.typingAttributes = [NSForegroundColorAttributeName:UIColor.blackColor()]
let protectedRange = NSMakeRange(0, 6)
let intersection = NSIntersectionRange(protectedRange, range)
if intersection.length > 0 {
return false
}
if range.location == 12 {
return true
}
if range.location + range.length > 12 {
return false
}
return true
}
This will lock down both the length at 13 and the prefix can not be deleted. Everything typed will be UIColor.blackColor()
Then you can a method like the following in your viewDidLoad, to set the prefix.
func makePrefix() {
let attributedString = NSMutableAttributedString(string: "C-TAD-")
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.lightGrayColor(), range: NSMakeRange(0,6))
textField.attributedText = attributedString
}
Related Topics
Xcode Swift 3: Timer and Segue View Controller Error
Aws Cognito/Getting User Information from the Sub
Toggle Selectedrange Attributes in Uitextview
Enum Method Returning a Dynamic Type
Why Aren't My Custom Classes Appearing in the Dropdown in Interface Builder
Implementing a 'Report' Feature for Inappropriate Content Swift Firebase
Inserting Data into Realm Db with Progress
Ibeacon: Get Advertisement Package Faster
Problem Creating and Writing a Subdirectory in Swift 5
How to Handle Async Requests in Swift
How to Make Text Typed in Textfield Undeletable
How to Perform Conditional Segue
Dispatchworkitem Not Notifying Main Thread
Cicolorcontrols & Uislider W/ Swift 4
How to Conditionally Define a Podspec Property Depending on Static or Dynamic Usage