Why UITextView/UITextField can't implement the UITextInput on iOS - ios

Apple supply an example to implement the UITextInput based on a UIView. I tried to do the same thing based on the UITextView/UITextField but failed. That's why?
Thanks

Apple uses a private class as delegate for UITextInput on these classes. That means you cannot hook your own code in there because you cannot subclass a private class.

Related

iOS 12 - oneTimeCode OTP delegate

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.

How do you implement the UIAccessibility protocol?

The "Accessibility Programming Guide For iOS" states:
Another way is to implement the isAccessibilityElement method of the UIAccessibility protocol in the implementation of your custom subclass. The following code snippet shows how to do this:
But when I am doing so, as in the following code:
class UITextLayerLabel : UIView, UIAccessibility {
XCode returns me this error:
[...] Use of undeclared type 'UIAccessibility'
What I am missing? A specific import? Is the protocol still available with iOS 10/XCode8?
As pointed out here, UIAccessibility is an informal protocol. For the difference between an informal protocol and a formal one, see here.
Basically, there is no type called UIAccessibility. Actually, UIView is already conforming to UIAccessibility. To make your custom view accessible, just override the properties and methods starting with accessibility.
So when do you need to implement UIAccessibility? As stated here,
You can use UIAccessibilityElement to provide information about an
icon or text image is not automatically accessible because it does not
inherit from UIView (or UIControl ). A view that contains such
nonview items creates an instance of UIAccessibilityElement to
represent each item that needs to be accessible.

How to apply style to all UIViews programatically

I have a class that defines all styles on a UIVIew.
They are all predefined but I'm not sure when to fire this.
When I try to create an extension for this:
extension UIView
{
func willMoveToSuperview(newSuperview: UIView?)
{
self.stylize() // Another extension somewhere (not here my problem)
}
}
And I'm getting this error:
Method 'willMoveToSuperview' with Objective-C selector conflicts with
previews declaration with the same Objective-c selector
I have tried to override it, but didn't worked either.
Any ideas on how to be able to apply a same behaviour when all of my UIViews will become visible?
You can use Swizzling technic to customize UIView's function. Take a look at:
http://nshipster.com/method-swizzling/ (objective-c)
or
http://nshipster.com/swift-objc-runtime/ (swift)
Hope that helps.
Even though Swift's Extensions are similar to Categories from Objective-C, what you are trying to do is not allowed in Swift.
You cannot override existing functionality:
Extensions can add new functionality to a type, but they cannot override existing functionality.
Source: Swift Extensions - Apple Documentation
Depending on what it is that you are trying to style, you might want to take a look at UIAppearance, it will allow you to style default colors for the UINavigationBar, amongst other things. NSHipster has a good post about it: NSHipster - UIAppearance
You can create a subclass of UIView with the method .stylize().
Then each view you create, you inherit of you UIView subclass.
You'll be able to cal .stylize() on each UIViewSubclass. Simply write the style code inside the subclass and inherite.
Or
Use a category to add the method to the existing UIView class.
See : https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html
Outside of swizzling (not generally recommended), or subclassing as noted by David in his answer, there isn't really a way to override existing methods on a class and its subclasses.
One thing you might try is creating a base class for your view controller instead of all your views. In your view controller base class, you could override viewWillLayoutSubviews to recurse through the view hierarchy and call stylize on each view. This means you would be using the subclass approach in fewer places (just view controllers as opposed to all views).
Another thing you might consider if taking the subclassing approach with UIView is that if you are subclassing anyway, you can take advantage of things like #IBDesignable and #IBInspectable to better integrate those UIView subclasses with storyboards and live preview.
I wrote a Swift library which does exactly this, and it works well for the type of styling it seems you want to do: https://github.com/daniel-hall/Stylish

Get UITextView text without delegate

I have tried to make a location autocomplete text view class by subclassing UITextField and use Google Place Autocomplete API. This works great, but I have a design error due to the implementation. To observe when the user types text, I set the UITextFieldDelegate to self in the custom subclass and track changes to the typed text in textView:shouldChangeTextInRange:replacementText:. This works, but here is the design error: If someone now wants to check what is typed into the custom subclass by setting the delegate to something new, the delegate of my class is not set to the object of the class itself anymore. Now the custom class is useless. Is there any way to either get the text as it is typed without the delegate, prevent the delegate from being changed, or in any other way fix my problem?
A few options I have though about that could work, but in a bad way:
Check regularly what the text property is: Should be obvious why busy waiting is a stupid idea
Override the delegate property and set it to private: Not sure if this will even work, but if it did, the class is no longer a proper subclass of UITextField and all delegate methods are unavailable when implementing my subclass.
Provide a new delegate for further use of the delegate: Allows someone to get the same things as the UITextFieldDelegate provides, but it still messes up the documentation and proper implementation of UITextField
Delegates in UIKit I normally one to one connections. Which can cause the problem you have described.
If you want multiple delegates of a UITextField I would derive a class from UITextField for example MYTextField and add a method to addDelegate and removeDelegate that maintains a list of delegates. The sent the MYTextField's delegate to itself and broadcast any delegate method to all listeners in the delegate array.
this post shows example code on how do maintain a list of multiple delegates.
Delegation to multiple objects

Custom Delegate for a custom View

I m using Xamarin for iOS and I have a custom View which inherit from UIView.
I would like to add a custom delegate to that view.
So far I found that:
Delegate (not useful) example
I want my delegate to be on his own and won't inherit from any other known delegate.
There is no delegate property on UIView (see Apple docs). It does exists in some subclasses, like UITextView (and other types).
What you can do (beside using the base classes provided) is:
(with the unified API) create your own classes that implements the IUITextViewDelegate interface and assign it to the Delegate property;
Create any class that conforms to the delegate (i.e. minimally all required members), add the required [Export], and assign it to the WeakDelegate property.

Resources