Keyboard extensions on iOS are subclasses of the UIInputViewController class and have the textDocumentProxy property to interact with the underlying document. The textDocumentProxy object exposes some important traits of the document, like the autocapitalization type. The question is, how does the keyboard extension know when the underlying document changes?
For example, when I tap to compose a new message in the Messages app, the “To” field uses different input traits than the message body input box. But since the keyboard doesn’t dissapear when switching focus from one field to the other, the text document proxy object changes on the fly. Can the keyboard extension notice such a change?
I’ve tried watching both the textDocumentProxy and [[self textDocumentProxy] autocapitalizationType] properties through KVO, but that doesn’t work. Checking the autocapitalizationType property using a timer reveals the change, but obviously I’d like to avoid a polling solution.
My UIInputViewController supports the UITextInput protocol, which has a textDidChange method. From textDidChange, I compare self.textDocumentProxy with my own self.currentTextProxy property. When the two differ, I update self.currentTextProxy, then refresh my GUI based upon the self.textDocumentProxy’s UITextInputTraits.
Related
Is there any delegate getting fired when the user taps the OTP suggestion that iOS provides?
I know that I could use UITextFieldDelegate methods to detect changes in the textfield's text property, but knowing that the user has pressed the button would make things so much easier...
According to Apple's article: About the Password AutoFill Workflow
For iOS apps, the system always sends a textDidChangeNotification notification when a view has been modified. It also calls one of the delegate methods of the view—but the exact method depends on the view’s type:
UITextField: The system calls your UITextFieldDelegate object’s textField(_:shouldChangeCharactersIn:replacementString:) method.
UITextView: The system calls your UITextViewDelegate object’s textView(_:shouldChangeTextIn:replacementText:) method.
Custom View adopting the UITextInput protocol: The system calls the insertText(:) method or replace(:withText:) in the UIKeyInput protocol.
You can create a subclass of UITextField or UITextView and override insertText(:) method and replace(:withText:) method, it will be called when user tap quickbar.
In my case, I found that when I got a text in Should change Charater I got two empty spaces, there I come to know that it is autofill characters, so according to it, I update my four text field one by one.
I am working with keyboard resign features in iPhone app development. I would like to know why
self.textField.delegate = self
needs to be included into the viewDidLoad of a viewController. I have tried to find reasons of this but no explanation has been clear so far.
A few points
The reason you need to set the delegate is because without it the view doesn't know about the view controller. So it wouldn't know about your method textFieldDidEndEditing and it would never be called.
That is the basic premise of delegate, you are telling that object, "here is an object that I want you to call methods on"
It doesn't have to be set in viewDidLoad - but it's often the most convient place to set up delegates for views.
The delegate doesn't have to be the view controller (self), in your case it's the simplest way, but with a UITableView its common to have another class be the delegate so that all the logic isn't in one place and so it can be changed.
The UITextFieldDelegate protocol defines methods that you use to manage the editing and validation of text in a UITextField object. All of the methods of this protocol are optional.
A text field calls the methods of its delegate in response to important changes. You use these methods to validate text that was typed by the user, to respond to specific interactions with the keyboard, and to control the overall editing process. Editing begins shortly before the text field becomes the first responder and displays the keyboard (or its assigned input view).
From more info. check apple doc.
Its not necessary to use self.textField.delegate = self if you don't want to manage the editing and validation of text in a UITextField object as all the methods of UITextFieldDelegate is optional.
For your other questions like what does .delegate = self do??
When you "set the delegate," what you are doing is saying where you want the messages to go.
Hence,
blah.delegate = amazingPlace will send the messages to "amazingPlace".
blah.delegate = somewhereElse will send the messages to "somewhereElse".
blah.delegate = self will send the messages to you.
... check this source link for details
Delegates are key concepts in iOS development so I'd suggest taking a good look at the documentation for them. It can be particularly useful to create your own custom delegates in certain situations too so understanding and using them in the right places can really help improve the structure of your projects.
There are a couple of key reasons for using them. Firstly, they allow safe communication between classes. In your example, the textField object that you're using is communicating back to your view controller. This is why you need to set your view controller as its delegate. Otherwise the text field doesn't have a delegate object (your view controller) to communicate with. The text field fires certain methods at certain times, such as textFieldDidBeginEditing, and calls these on its delegate object if it has one. When you register your view controller as the text view's delegate you can tap into these callbacks.
The other benefit is that delegates allow you to separate concerns and encapsulate or abstract responsibilities. It might be that the main concern for the text view is how to handle text in its view but not necessarily what to do when has been entered, or when the return button in the keyboard is pressed, or how to validate text that has been input. It's better that these tasks are handed over to something else, such as a delegate (in Obj-C parlance), and that is why in your example you have to register one class as the delegate for another.
As stated before, UITextfield delegation allows you to control events on your textfield.
You ll have the ability to edit functions like
textFieldShoulEndEditing
or
textFieldDidEndEditing
in order to add custom rules, for example : text validation.
Take a look at Apple doc.
If you don't need it, you can delete this line and UITextfieldDelegate on your class declaration.
You need to either set the delegate of a UITextField in code with self.textField.delegate = self
or make your viewcontroller (or any other class) a delegate with class MyViewController: UITextFieldDelegate and set the delegate of the UITextField in the storyboard by control dragging from the textfield to the viewController.
I'm building a custom keyboard
and I'm implementing the following delegate methods in my InputViewController.
But I always get _textInput = nil_
- (void)textWillChange:(id<UITextInput>)textInput
- (void)textDidChange:(id<UITextInput>)textInput
- (void) selectionWillChange:(id<UITextInput>)textInput
- (void) selectionDidChange:(id<UITextInput>)textInput
Does anybody know how to fix it?
Is it nil for a reason?
Do I need to implement something by myself?
Good question. But it seems that UITextInputDelegate is not a protocol that you implement.
From Apple Docs titled Lower Level Text-Handling Technologies:
When changes occur in the text view due to external reasons—that is,
they aren't caused by calls from the text input system—the UITextInput
object should send textWillChange:, textDidChange:,
selectionWillChange:, and selectionDidChange: messages to the input
delegate (which it holds a reference to). For example, when users tap
a text view and you set the range of selected text to place the
insertion point under the finger, you would send selectionWillChange:
before you change the selected range, and you send selectionDidChange:
after you change the range.
And from the docs on UITextInputDelegate:
The UIKit provides a private text input delegate, which it assigns at
runtime to the inputDelegate property of the object whose class adopts
the UITextInput protocol.
The implication of the above is that we don't implement these delegate methods; we use them to inform the inputDelegate that you have changed your text or selection via means other than keyboard input.
Here is an example method that illustrates this:
- (void)delete:(id)sender;
{
if (selection && ![selection isEmpty]) {
[inputDelegate textWillChange:self];
[inputDelegate selectionWillChange:self];
[self replaceRange:selection withText:#""];
[inputDelegate selectionDidChange:self];
[inputDelegate textDidChange:self];
}
}
Sample code with more examples here.
I have a custom UITextInput-based text editor. It works very well, except for multi-stage input via marked text.
My marked region renders correctly, and marked text is inserted, but the candidate list above the keyboard is blank.
For example, here is the Japanese (Kana) keyboard showing suggestions on a standard UITextView:
And here is my custom editor displaying the same marked text:
I have spent several days debugging this issue and have found that the cause is private class UIKeyboardImpl returning NO for the method delegateSupportsCorrectionUI
If I override this method in a category on UIKeyboardImpl and return YES instead, then multistage input suggestions correctly display for my text editor. However this does not address the underlying cause of the problem (and it's not usable).
I have also looked very closely at Apple's SimpleTextInput sample code. This implements a basic Core Text editor. SimpleTextInput correctly displays multistage input suggestions, however I cannot seem to find a single difference in its implementation of UITextInput that causes it to work and mine to break.
(In fact, I am unable to "break" the SimpleTextInput sample's ability to display multi-stage input. Which leads me to think that my focus on the UITextInput implementation is the wrong track. And it is something else altogether.)
Okay, this is a bit embarrassing. I just now noticed:
#property(nonatomic, readonly) UIView *textInputView
Discussion
The view that both draws the text and provides a coordinate system for
all geometric values in this protocol. (This is typically an instance
of the UITextInput-adopting class.) If this property is unimplemented,
the first view in the responder chain is selected.
In the documentation.
I had stupidly #synthesize'd this property and forgot about it, meaning my UITextInput implementation was returning a nil textInputView. Simply leaving it unimplemented chooses the first view from the responder chain as described, which provides the text system with the necessary coordinate system to handle auto-correction and multistage input suggestions.
This was after three days of debugging. Now I feel stupid.
I'm interested in doing something similar to this, however the component subviews of MFMessageComposeViewController are a much different than MFMailComposeViewController.
I figured out how to set focus to the input that let's you to type your message text by simply calling setRecipients: with an array containing a blank NSString. However, I'd like to paste non-text from the pasteBoard into the input, so I can't simply use setBody:.
Problem:
What I need to do is get a reference to the actual text field that is the current first responder for my MFMessageComposeViewController. This way, I have a "sender" I can pass to UIPasteboard's paste: method. The problem is, I can't seem to walk the subview hierarchy the same way as MFMailComposeViewController, so I can't find out which view is first responder.
I've even tried this, but the view is always returned as nil if I do a [myMessageVC.view findFirstResponder]
Word of caution, you're not supposed to have your hands inside that view. Apple will refuse your app for doing so. You are only allowed to set the body and recipients.
Important The message composition interface itself is not customizable
and must not be modified by your application. In addition, after
presenting the interface, your application is unable to make further
changes to the SMS content. The user can edit the content using the
interface, but programmatic changes are ignored. Thus, you must set
the values of content fields, if desired, before presenting the
interface
http://developer.apple.com/library/ios/#documentation/MessageUI/Reference/MFMessageComposeViewController_class/Reference/Reference.html