我正在尝试将一个方便失败的初始值设定项添加到UIFont
作为扩展名。所以UIFont
已经有一个失败的初始化程序:
open class UIFont : NSObject, NSCopying {
...
public init?(name fontName: String, size fontSize: CGFloat)
...
}
所以我想创建一个方便的初始化器来调用这个,类似于下面的代码:
public convenience init?(name fontName: String, size fontSize: CGFloat, weight fontWeight: String) {
self.init(name: fontName + "-" + fontWeight, size: fontSize)
}
到目前为止一切顺利,这完美无缺。现在我想添加一些自定义逻辑,例如:
public convenience init?(name fontName: String, size fontSize: CGFloat, weight fontWeight: String) {
if let font = self.init(name: fontName + "-" + fontWeight, size: fontSize) {
self = font
}
else if let font = self.init(name: fontName, size: fontSize) {
self = font
}
else {
//
// Add some failback code
//
return nil
}
}
这就是问题的起点。我想要做的是一个基本的便利API,但我无法设法有条件地初始化字体。在上面的示例中,if let font = self.init
行中存在语法错误,并显示:Initializer for conditional binding must have Optional type, not '()'
。但是这个初始化程序实际上是可选的,由UIFont
类定义(见上文),所以我没有看到问题。我尝试返回字体而不是将其分配给self
,但没有任何区别。
所以我的问题是:如何在失败的初始化程序中正确实现条件逻辑?
可能是我在这里做错了,或者这可能只是Swift缺少功能/错误?
答案 0 :(得分:1)
Swift初始化是该语言中最令人困惑的部分之一,特别是如果您来自Objective-C。简短的回答是:
与Objective-C初始值设定项不同,Swift初始值设定项不返回值。
因此,当你写:
public convenience init?(
name fontName: String, size fontSize: CGFloat, weight fontWeight: String
) {
let font = self.init(name: fontName + "-" + fontWeight, size: fontSize)
font
的类型为Void
。是的,我知道,它确实引起了人们的注意,因为它与ObjC的模型不同。在Swift中,您将初始化工作委托给另一个初始化工具,但您并未直接管理该实例。因此,您可以将其称为缺失功能。
简单的解决方法是使用工厂方法而不是初始化方法:
public static func from(
name fontName: String, size fontSize: CGFloat, weight fontWeight: String
) -> UIFont? {
if let font = self.init(name: fontName + "-" + fontWeight, size: fontSize) {
return font
}
else if let font = self.init(name: fontName, size: fontSize) {
return font
}
else {
//
// Add some failback code
//
return nil
}
}