How do you implement the UIAccessibility protocol? - ios

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.

Related

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

How to show subclass of UIControl in View Controller

I would like to be able to interact with the UIControl I have made, and therefore want it in my ViewController.
What I tried
I subclassed UIControl (1).
Then I added a UIView to my View Controller and assigned it the new class (2).
But in Interface Builder I am not able to set my outlets to the buttons contained in the new class (1)?!
1:
2:
UIControl's documentation confirms that it is a subclass of UIView, and I should therefore be able to connect the outlets, right?
What am I missing here? :/
Off-course you can't add IBOutlet because buttons what you added to WeekdayControl are in UIViewController, you can't add Outlet to WeekdayControl, buttons only subviews of WeekdayControl, UIViewController is boss here, and you can add outlet only to UIViewController. (Sorry for my English)
Better create you buttons programatically in WeekdayControl.
Must read first:-
You cannot use the UIControl class directly to instantiate controls.
It instead defines the common interface and behavioral structure for
all its subclasses.
The main role of UIControl is to define an interface and base
implementation for preparing action messages and initially dispatching
them to their targets when certain events occur
So, you are doing wrong, if you really need to make a custom view or custom control then you can directly do it by creating a custom UIView and connecting the outlets directly with the view.
I think you missing the objective of subclassing a UIControl, it doesn't give rights to create outlets as it's a subclass of UIView,just read this lines what it is stated in the docs:-
Subclassing Notes
You may want to extend a UIControl subclass for either of two reasons:
To observe or modify the dispatch of action messages to targets for
particular events
To do this, override sendAction:to:forEvent:, evaluate the passed-in
selector, target object, or UIControlEvents bit mask, and proceed as
required.
To provide custom tracking behavior (for example, to change the
highlight appearance)
To do this, override one or all of the following methods:
beginTrackingWithTouch:withEvent:,
continueTrackingWithTouch:withEvent:, endTrackingWithTouch:withEvent:.

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.

Clarification around UIViewController<Delegate> *_variable; declaration in iAdSuite tabbed example (iOS)

From Apples iADSuite tabbed example there is a variable defined with delegate.
UIViewController<BannerViewContainer> *_currentController;
later it's cast as such
_currentController = (UIViewController<BannerViewContainer> *)_tabBarController.selectedViewController;
Whats the significance of using "BannerViewContainer" in the declaration, how it relates to the later cast and what's happening under the covers here?
Regards
Jim
There's nothing to do with delegates here. BannerViewContainer is a protocol. (You might be confused because delegation is often defined via protocols.)
Declaring a variable or parameter with an angle-bracketed protocol name means that anything assigned to it must be an object which conforms to that protocol: if you try to pass an instance of UIViewController or some subclass thereof, you'll get a compiler warning unless that instance is of a UIViewController subclass which declares conformance to the BannerViewContainer protocol. (That is, you can pass an instance of FooViewController if its header file reads #interface FooViewController : UIViewController <BannerViewContainer>.)
The cast you see later follows the same pattern as many casts: it's a case where the programmer knows that the object he's assigning meets the requirements for that variable, but the reference he's using doesn't have a matching declaration. That is, the tab bar controller only knows that its selected view controller is a UIViewController (or any subclass thereof), but the programmer knows that the views he put into the tab bar are all UIViewController subclasses conforming to the BannerViewContainer protocol.

Why UITextView/UITextField can't implement the UITextInput on 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.

Resources