Marking plain -init to have a nullable return type without a warning

914 views Asked by At

I have an ObjC class inheriting from NSObject that wraps some third-party library macros so that I can use their functionality in Swift. The class has an ivar that's a container type from the library. Creation of the container can fail, and if it does, the instantiation of my class should fail too. So I marked -init as nullable.

@interface BasketWrapper : NSObject

/**
 * @abstract  Create an empty basket
 */
 - (nullable instancetype)init;    // ⚠️ Conflicting nullability specifier

@end

@implementation
{
    LibraryBasket * _basket;
}

- (instancetype)init
{
    self = [super init];
    if( !self ) return nil;

    // Can't really do anything without the wrapped item.
    _basket = LibraryBasket_Create();
    if( !_basket ) return nil;

    return self;
}

Unfortunately that -init declaration produces a compiler warning

Conflicting nullability specifier on return types, '_Nullable' conflicts with existing specifier 'nonnull'

pointing at NSObject's declaration.

As a workaround, I've marked the warning ignored with a pragma, and the method appears in Swift as failable.

Another option I considered was to mark plain -init unavailable and make a class method, +empty, instead. But then that's annoying because a) I can't use Swift initializer syntax, and b) init is unavailable in the class's own implementation too.

Is there some way to override the nullability of the inherited init without the warning?

1

There are 1 answers

0
Cristik On

You could declare a factory method having the same name as the type:

@interface BasketWrapper : NSObject

+ (nullable instancetype)basketWrapper;

/**
 * @abstract  Create an empty basket
 */
- (instancetype)init NS_UNAVAILABLE;

@end

This will make the warning go away and allow you to make use of the failable initializer.