Ale*_*ant 2 swift swift-extensions
我试图在UIColor上创建一个扩展函数,该函数可以采用Card.Colour类型的参数并将UIColor返回给调用方。
button.backgroundColor = UIColor.getColour(cardColour: cardToDeal.colour)
extension UIColor {
func getColour(cardColour: Card.Colour) -> UIColor {
switch cardColour {
case .Red:
return UIColor.red
case .Green:
return UIColor.green
case .Blue:
return UIColor.blue
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试执行此操作时,UIColor.getColour的扩展功能要求我在扩展方法中输入UIColor类型的参数,而不是Card.Colour的指定类型。
但是,当我将getColour的扩展功能更改为:
static func getColour(cardColour: Card.Colour) -> UIColor {
class func getColour(cardColour: Card.Colour) -> UIColor {
Run Code Online (Sandbox Code Playgroud)
它允许我传递Card.Colour类型的参数
为什么是这样?为什么将函数更改为静态函数或类函数会更改需要传入的类型?
提前致谢!
(详细的答案将不胜感激)
记住那UIColor是一堂课。类有点像用于创建符合该类的实例或对象的蓝图。UIColor.red是UIColor该类实例的示例。
当您func在类内部定义一个内部(以您的情况作为扩展)时,Swift假定您要将其添加func到蓝图中,而该蓝图又将在UIColor该类的所有实例中可用UIColor.red。
您也可以func将其放置在模块的顶层,而不是放置在所有类的外部,以将其定义在所有类之外extension。
但是,为了使您的函数井井有条,您可以将类似的函数放在类名中。您只需要告诉Swift,您并没有在尝试将函数添加到将应用于所有实例的蓝图中,而是想要拥有一个名称以类名作为前缀的函数。
这是一个说明用法差异的示例:
class Test {
func notStatic() {
print("called from an instance")
}
static func thisIsStatic() {
print("called on class name directly")
}
}
let instance = Test() // this is an *instance* of Test
instance.notStatic() // we can call a non static func on instance
Test.thisIsStatic() // we can call a static func directly on the class only
Run Code Online (Sandbox Code Playgroud)
现在,让我们再回到您的特定示例。请注意,在您的示例中,您从的实例开始,Card.Colour并尝试创建的新实例UIColor。
换句话说,将a添加func到UIColor 实例(即non- static或class)对您没有用,因为您还没有实例UIColor。
创建类的新实例的惯用方式是使用初始化程序(init)。因此,您可以将函数变成UIColor上的初始化程序,如下所示:
extension UIColor {
convenience init(cardColour: Card.Colour) {
switch cardColour {
case .Red: self.init(cgColor: UIColor.red.cgColor)
case .Blue: self.init(cgColor: UIColor.blue.cgColor)
case .Green: self.init(cgColor: UIColor.green.cgColor)
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您只需致电UIColor(cardColour: .Red)即可获得想要的东西。需要注意的是在执行,我将UIColor.red要cgColor和后面作为一个快速黑客攻击。可以UIColor针对每种情况随意使用您认为合适的初始化程序Card.Colour。
但是还有另一种方式,我认为这更优雅。既然你已经有一个实例的Card.Colour,可以延长Card.Colour使用,让您的一个功能UIColor对应的实例。在该函数中,您可以Card.Colour使用关键字引用实例self。
由于您已经Card.Colour通过拥有实例self,因此您无需将任何参数传递给该函数。这使您可以使用一个很酷的功能,称为计算属性,以使用法更加美观。
这就是您将这样的扩展名添加到的方式Card.Colour:
extension Card.Colour {
var uiColor: UIColor {
switch self {
case .Red: return .red
case .Blue: return .blue
case .Green: return .green
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以得到一个UIColor从Card.Colour这样Card.Colour.Red.uiColor或mainColour.uiColor,其中mainColour是类型Card.Colour。
最后,正如Leo Dabus在评论中指出的那样,Swift的命名约定是大小写应以小写字母开头。您应该使用Card.Colour.red而不是Card.Colour.Red,等等。这些约定在Swift 3左右出现了。在此之前,通常将案例名称大写。