Unavailable initializers in -Swift.h


(Svein Halvor Halvorsen) #1

Hi,

In Objective-C, I've often attributed initializer from super classes as
unavailable. Like this;

@class Dependency;

@interface SomeClass : NSObject

- (nullable instancetype)init __unavailable;

- (nonnull instancetype)initWithDependency:(nonnull Dependency *)dependency;

@end

This makes the compiler complain if I try to instantiate [[SomeClass alloc]
init];

However, If I declare a Swift class like this:

class SomeClass: NSObject {

    init(dependency: Dependency) {

        super.init()

    }

}

The generated header file will look like this:

@interface SomeClass : NSObject

- (nonnull instancetype)initWithDependency:(Dependency * _Nonnull)dependency
OBJC_DESIGNATED_INITIALIZER;

@end

If I try to use init, it will be a run time error, and not a compile time
error.
It there any way I can make Swift create the desired objc header file?

Svein Halvor


(Svein Halvor Halvorsen) #2

This is even worse if I want to create a singleton, and ensure that the
only way to access it, is through a static let on the class:

class Singleton: NSObject {
    static let instance = Singleton()
    private override init() {
        super.init()
    }
}

In Swift, I can't instantiate this class, since it has no internal/public
initializers. However, since it inherits from NSObject (which is necessary
to access it from objc), I can initialize it from objc, even though it's
private. Annotating it with @nonobjc doesn't help either.

Is there a reason why Swift doesn't automatically declare accessors from
the super class, that are either private or @nonobjc in the Swift subclass
implementation, as __unavailable?

Is there anyway I can enforce it using some (combination of) attributes?

sv.

···

2016-06-08 15:12 GMT+02:00 Svein Halvor Halvorsen <svein.h@lvor.halvorsen.cc >:

Hi,

In Objective-C, I've often attributed initializer from super classes as
unavailable. Like this;

@class Dependency;

@interface SomeClass : NSObject

- (nullable instancetype)init __unavailable;

- (nonnull instancetype)initWithDependency:(nonnull Dependency
*)dependency;

@end

This makes the compiler complain if I try to instantiate [[SomeClass alloc]
init];

However, If I declare a Swift class like this:

class SomeClass: NSObject {

    init(dependency: Dependency) {

        super.init()

    }

}

The generated header file will look like this:

@interface SomeClass : NSObject

- (nonnull instancetype)initWithDependency:(Dependency * _Nonnull)dependency
OBJC_DESIGNATED_INITIALIZER;

@end

If I try to use init, it will be a run time error, and not a compile time
error.
It there any way I can make Swift create the desired objc header file?

Svein Halvor


(Jordan Rose) #3

Seems reasonable to me. It looks like SR-746 <https://bugs.swift.org/browse/SR-746> tracks the same thing. Patches welcome!

Jordan

···

On Jun 8, 2016, at 7:06, Svein Halvor Halvorsen via swift-users <swift-users@swift.org> wrote:

This is even worse if I want to create a singleton, and ensure that the only way to access it, is through a static let on the class:

class Singleton: NSObject {
    static let instance = Singleton()
    private override init() {
        super.init()
    }
}

In Swift, I can't instantiate this class, since it has no internal/public initializers. However, since it inherits from NSObject (which is necessary to access it from objc), I can initialize it from objc, even though it's private. Annotating it with @nonobjc doesn't help either.

Is there a reason why Swift doesn't automatically declare accessors from the super class, that are either private or @nonobjc in the Swift subclass implementation, as __unavailable?

Is there anyway I can enforce it using some (combination of) attributes?

sv.

2016-06-08 15:12 GMT+02:00 Svein Halvor Halvorsen <svein.h@lvor.halvorsen.cc <mailto:svein.h@lvor.halvorsen.cc>>:
Hi,

In Objective-C, I've often attributed initializer from super classes as unavailable. Like this;

@class Dependency;
@interface SomeClass : NSObject
- (nullable instancetype)init __unavailable;
- (nonnull instancetype)initWithDependency:(nonnull Dependency *)dependency;
@end

This makes the compiler complain if I try to instantiate [[SomeClass alloc] init];

However, If I declare a Swift class like this:

class SomeClass: NSObject {
    init(dependency: Dependency) {
        super.init()
    }
}

The generated header file will look like this:

@interface SomeClass : NSObject
- (nonnull instancetype)initWithDependency:(Dependency * _Nonnull)dependency OBJC_DESIGNATED_INITIALIZER;
@end

If I try to use init, it will be a run time error, and not a compile time error.
It there any way I can make Swift create the desired objc header file?

Svein Halvor

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users