JAL
JAL

Reputation: 42449

Using __kindof with non-collection types

Xcode 7 added the __kindof decorator to object declarations:

KindOf. Objects declared as __kindof types express "some kind of X" to the compiler and can be used within generic parameters to constrain types to a particular class or its subclasses. Using __kindof allows constraints to be more flexible than an explicit class, and more explicit than just using id.

The most obvious use case for __kindof is with collection types to explicitly state what kind of objects will be in a particular collection. From the UIStackView header:

- (instancetype)initWithArrangedSubviews:(NSArray<__kindof UIView *> *)views; // Adds views as subviews of the receiver.
@property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *arrangedSubviews;

This explicitly states that each NSArray will contain objects that are or inherit from UIView.

But there are some cases where __kindof is used on a non-collection typed object, such as in the UIStoryboardSegue header:

@property (nonatomic, readonly) __kindof UIViewController *sourceViewController;
@property (nonatomic, readonly) __kindof UIViewController *destinationViewController;

What does the __kindof decorator change on non-collection-type objects?

Upvotes: 3

Views: 385

Answers (1)

JAL
JAL

Reputation: 42449

The most obvious case is when casting types:

UIViewController *vc = [[UIViewController alloc] init];
// SomeViewController inherits from UIViewController
SomeViewController *someViewController = vc; // Warning: Incompatible pointer type initializing 'SomeViewController *' with an expression of type 'UIViewController *'

__kindof UIViewController *otherVC = [[UIViewController alloc] init];
SomeViewController *someVC = otherVC; // no warning

This is why in a UIViewController's prepareForSegue method, casting segue.destinationViewController to another UIViewController subclass does not show a warning:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    SomeViewController *someVC = segue.destinationViewController; // no warning
    // ...
}

Upvotes: 4

Related Questions