Reputation: 69
I am having trouble doing a simple text selection and change of attributes. I can't seem to get the program past the first step. It says that the selectedRange
is nil. Why is this happening? Is this a bug with something?
func selectText() {
if let textRange = textView?.selectedRange {
let attributes = [NSAttributedString.Key.font: UIFont(name: "Arial", size: 18.0)]
textView.textStorage.addAttributes(attributes as [NSAttributedString.Key : Any], range: textRange)
}
}
Edit with code from @DionizB (not working)
I call it from another Swift file that holds the view for the KeyboardAccessory. Code in that file is:
class KeyboardAccessory: UIView {
let VC = ViewController()
@IBAction func boldButtonTapped(_ sender: Any) {
print("boldButtonTapped -> Sending to bold()")
VC.bold()
}
}
Code now in main ViewController is:
var selectedRange: NSRange?
func textViewDidChangeSelection(_ textView: UITextView) {
selectedRange = textView.selectedRange
print(selectedRange)
}
func bold() {
print("Starting bold()")
print(selectedRange)
if let textRange = selectedRange {
print(textRange)
let attributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17, weight: UIFont.Weight.thin)]
textView.textStorage.addAttributes(attributes as [NSAttributedString.Key : Any], range: textRange)
}
}
textViewDidChangeSelection is printing the selectedRange but when bold() is called from the KeyboardAccessory View it prints nil! How I load the AccessoryView.
override func viewDidLoad() {
super.viewDidLoad()
textView.inputAccessoryView = Bundle.main.loadNibNamed("KeyboardAccessory", owner: self, options: nil)?.first as! UIView?
}
Upvotes: 1
Views: 206
Reputation: 1507
On viewDidLoad()
make sure you add textView.delegate = self
.
Also in your class inherit from UITextViewDelegate
.
Then call your selectText()
in textViewDidChangeSelection(_:)
func textViewDidChangeSelection(_ textView: UITextView) {
selectText()
}
And it will work properly.
EDIT
Normally it should work even when you call your selectText()
inside your button action. But since it's not working, let's do a workaround:
Declare var selectedRange: NSRange?
in your class.
Then in
func textViewDidChangeSelection(_ textView: UITextView) {
selectedRange = textView.selectedRange
}
And in your selectText()
do this
func selectText() {
if let textRange = selectedRange {
let attributes = [NSAttributedString.Key.font: UIFont(name: "Arial", size: 18.0)]
textView.textStorage.addAttributes(attributes as [NSAttributedString.Key : Any], range: textRange)
}
}
EDIT for AccessoryView
Update your KeyboardAccessory:
class KeyboardAccessory: UIView {
var boldAction: (() -> Void)? // This is a closure, give it a read after making your button work
@IBAction func boldButtonTapped(_ sender: Any) {
print("boldButtonTapped -> Sending to bold()")
boldAction?()
}
}
Try to cast your loaded nib as KeyboardAccessory and access your action like this:
override func viewDidLoad() {
super.viewDidLoad()
var keyboardAccessory = Bundle.main.loadNibNamed("KeyboardAccessory", owner: self, options: nil)?.first as! KeyboardAccessory?
keyboardAccessory.boldAction = { [weak self] in // to avoid retain cycles, read also about these
self?.selectText()
}
textView.inputAccessoryView = keyboardAccessory
}
Upvotes: 1