Swift 没有在 CAGradientLayer 上调用 class init 方法
Swift not calling class init method on CAGradientLayer
我有一个 Objective-C 的 'CAGradientLayer' 子类,它覆盖了 '+ (CAGradientLayer *)layer' 初始值设定项。它已正确包含在我的 Bridging-Header
中
#import "ONCGradientLayer.h"
@implementation ONCGradientLayer
+ (ONCGradientLayer *)gradientLayer {
return [ONCGradientLayer layer];
}
+ (ONCGradientLayer *)layer {
ONCGradientLayer * layer = [super layer];
layer.colors = @[(id)[[UIColor colorWithWhite:0.0 alpha:1] CGColor], (id)[[UIColor colorWithWhite:0.1 alpha:1] CGColor]];
layer.startPoint = CGPointMake(0, 0);
layer.endPoint = CGPointMake(0, 1);
return layer;
}
通过调用 [ONCGradientLayer layer]
或 [ONCGradientLayer gradientLayer]
,这一切都按照 Objective-C 的预期工作
当我尝试从 swift 调用它时,我得到一个编译器警告,该方法已重命名 init
,所以我必须调用 ONCGradientLayer()
但是,不起作用,并且永远不会调用覆盖的初始化程序。
我可以通过添加一个不同名称的初始值设定项来解决这个问题:
+ (ONCGradientLayer *)swiftInit {
return [ONCGradientLayer layer];
}
我可以在 swift 中使用 ONCGradientLayer.swiftInit()
成功调用它
发生什么事阻止我调用 ONCGradientLayer()
并获取覆盖的初始化程序?
更新:
我可以通过将 ONCGradientLayer()
重构为使用 init
方法来使 ONCGradientLayer()
工作,但我仍然很好奇为什么其他方法不起作用。
- (instancetype)init {
if (self = [super init]) {
self.colors = @[(id)[DEFAULT_BACKGROUND_COLOR CGColor], (id)[[UIColor colorWithWhite:.1 alpha:1] CGColor]];
self.startPoint = CGPointMake(0, 0);
self.endPoint = CGPointMake(0, 1);
}
return self;
}
这都是关于一个名为 Clang Importer. 的 Swift 组件,它负责将 Objective-C 方法名称翻译成 Swift 方法名称(反之亦然)。
Clang Importer 假定如果 Objective C class 具有与 class 同名的 class 方法,除了前缀和小写,可能由 with
扩展, 它是一个 class 工厂方法。
它还假定class工厂方法与名称构造方法相同的初始化器有效相同,并且完全隐藏相应的工厂方法,因为对于 ARC,两者之间没有有意义的区别。
EXAMPLE: NSString has factory method stringWithFormat:
and initializer initWithFormat:
.
Well, string
is the same as NSString stripped of its prefix and lowercased; so the Clang Importer assumes that stringWithFormat:
is a factory method. Moreover, it is constructed just like initWithFormat:
, so the Clang Importer assumes they are effectively the same, and hides the former.
Therefore you have to say String(format:)
, meaning String.init(format:)
, in Swift. [The Clang Importer also strips the with
, but that's another story.] There is no String.withFormat(_:)
(or similar) in Swift, matching Objective-C stringWithFormat:
.
这正是您的 ONCGradientLayer 和 gradientLayer
的情况。您的 class 方法遵循 class 工厂方法命名约定。因此,多亏了 Clang Importer,如果有一个 init
—— 确实有 —— 那么 class 工厂方法就被隐藏了。因此,您必须改为调用 init
,在 Swift.
中说 ONCGradientLayer()
但是您没有将 init
定义为 return 修改后的 ONCGradientLayer,因此结果是没有您修改的普通层。
如果你不喜欢那样,你有两个选择。你已经发现它们是什么了!
更改 class 工厂名称,例如makeGradientLayer
。 (这正是您通过提供名称 swiftInit
所做的。)
或者,定义init
到return一个ONCGradientLayer,修改方式与layer
相同。 (你也是这么做的。)
我有一个 Objective-C 的 'CAGradientLayer' 子类,它覆盖了 '+ (CAGradientLayer *)layer' 初始值设定项。它已正确包含在我的 Bridging-Header
#import "ONCGradientLayer.h"
@implementation ONCGradientLayer
+ (ONCGradientLayer *)gradientLayer {
return [ONCGradientLayer layer];
}
+ (ONCGradientLayer *)layer {
ONCGradientLayer * layer = [super layer];
layer.colors = @[(id)[[UIColor colorWithWhite:0.0 alpha:1] CGColor], (id)[[UIColor colorWithWhite:0.1 alpha:1] CGColor]];
layer.startPoint = CGPointMake(0, 0);
layer.endPoint = CGPointMake(0, 1);
return layer;
}
通过调用 [ONCGradientLayer layer]
或 [ONCGradientLayer gradientLayer]
当我尝试从 swift 调用它时,我得到一个编译器警告,该方法已重命名 init
,所以我必须调用 ONCGradientLayer()
但是,不起作用,并且永远不会调用覆盖的初始化程序。
我可以通过添加一个不同名称的初始值设定项来解决这个问题:
+ (ONCGradientLayer *)swiftInit {
return [ONCGradientLayer layer];
}
我可以在 swift 中使用 ONCGradientLayer.swiftInit()
发生什么事阻止我调用 ONCGradientLayer()
并获取覆盖的初始化程序?
更新:
我可以通过将 ONCGradientLayer()
重构为使用 init
方法来使 ONCGradientLayer()
工作,但我仍然很好奇为什么其他方法不起作用。
- (instancetype)init {
if (self = [super init]) {
self.colors = @[(id)[DEFAULT_BACKGROUND_COLOR CGColor], (id)[[UIColor colorWithWhite:.1 alpha:1] CGColor]];
self.startPoint = CGPointMake(0, 0);
self.endPoint = CGPointMake(0, 1);
}
return self;
}
这都是关于一个名为 Clang Importer. 的 Swift 组件,它负责将 Objective-C 方法名称翻译成 Swift 方法名称(反之亦然)。
Clang Importer 假定如果 Objective C class 具有与 class 同名的 class 方法,除了前缀和小写,可能由 with
扩展, 它是一个 class 工厂方法。
它还假定class工厂方法与名称构造方法相同的初始化器有效相同,并且完全隐藏相应的工厂方法,因为对于 ARC,两者之间没有有意义的区别。
EXAMPLE: NSString has factory method
stringWithFormat:
and initializerinitWithFormat:
.Well,
string
is the same as NSString stripped of its prefix and lowercased; so the Clang Importer assumes thatstringWithFormat:
is a factory method. Moreover, it is constructed just likeinitWithFormat:
, so the Clang Importer assumes they are effectively the same, and hides the former.Therefore you have to say
String(format:)
, meaningString.init(format:)
, in Swift. [The Clang Importer also strips thewith
, but that's another story.] There is noString.withFormat(_:)
(or similar) in Swift, matching Objective-CstringWithFormat:
.
这正是您的 ONCGradientLayer 和 gradientLayer
的情况。您的 class 方法遵循 class 工厂方法命名约定。因此,多亏了 Clang Importer,如果有一个 init
—— 确实有 —— 那么 class 工厂方法就被隐藏了。因此,您必须改为调用 init
,在 Swift.
ONCGradientLayer()
但是您没有将 init
定义为 return 修改后的 ONCGradientLayer,因此结果是没有您修改的普通层。
如果你不喜欢那样,你有两个选择。你已经发现它们是什么了!
更改 class 工厂名称,例如
makeGradientLayer
。 (这正是您通过提供名称swiftInit
所做的。)或者,定义
init
到return一个ONCGradientLayer,修改方式与layer
相同。 (你也是这么做的。)