【问题标题】:UIButton as UIButton in swift?UIButton 作为 UIButton 在 swift 中?
【发布时间】:2023-08-29 19:21:01
【问题描述】:

我正在看这个 Swift 教程,有这样一行:

var button:UIButton = UIButton.buttonWithType(UIButtonType.System) as UIButton

两个问题:

  1. 为什么该行以as UIButton 结尾?用户想要创建一个系统类型的按钮,这条线还不够清晰吗?这似乎是多余的。
  2. 是否需要在该行的第一部分声明类型 UIButton?或者换句话说,声明它是不够的

var button = UIButton.buttonWithType(UIButtonType.System)

我的意思是,如果等号后面的部分正在初始化系统类型的按钮,编译器不足以推断buttonUIButton?我的意思是,Apple 说编译器很聪明地推断类型。

【问题讨论】:

  • 许多你的问题是我也想问的好奇基本问题(但我猜你比我早 2 年)学习曲线)。通常,除非在 SO 上询问,否则您不会找到此类问题的答案。

标签: swift


【解决方案1】:

您需要保持as UIButton 的低调。 buttonWithType()返回AnyObject!,而不是UIButton,所以向下转型是必要的。除此之外,您不需要使用: UIButton 显式键入变量。由于buttonWithType() 的返回类型向下转换为UIButton,因此变量类型将被推断为UIButton。这是你应该使用的:

var button = UIButton.buttonWithType(UIButtonType.System) as UIButton

【讨论】:

  • 而根本原因似乎是Objective-C方法buttonWithType:被声明为返回id而不是instancetype
  • Martin 的完美分析和完美评论!现在我明白了,AnyObject! =身份证!谢谢!!!
  • 从 Swift 1.2 开始,您需要使用 as! 强制向下转换
【解决方案2】:

除了已经给出的答案之外的一些其他背景: Objective-C方法

+ (id)buttonWithType:(UIButtonType)buttonType

返回id。这是声明“工厂方法”的“传统”方式 也可以从子类中使用。在

中不需要类型转换
UIButton *button = [UIButton buttonWithType: UIButtonTypeSystem];

因为id 可以转换为任何Objective-C 指针。

现在Swift中id的等价类型是AnyObject,上面的方法映射到

class func buttonWithType(buttonType: UIButtonType) -> AnyObject!

Swift 更加严格,并且 not 隐式转换类型,因此返回值必须显式转换为 UIButton

var button = UIButton.buttonWithType(UIButtonType.System) as UIButton

声明工厂方法的“现代”方法是instancetype(参见例如http://nshipster.com/instancetype/Would it be beneficial to begin using instancetype instead of id?)。一个简单的例子是 NSString 方法

+ (instancetype)stringWithCString:(const char *)cString encoding:(NSStringEncoding)enc

在 Swift 中映射到

class func stringWithCString(cString: CString, encoding enc: UInt) -> Self!

Self 是调用方法的对象的类型,因此 的返回类型

NSString.stringWithCString("foo", encoding: NSUTF8StringEncoding)

NSString!,返回类型是

NSMutableString.stringWithCString("bar", encoding: NSUTF8StringEncoding)

NSMutableString!在 Swift 中不需要类型转换。在下面的 例如,Swift 编译器“知道”strNSString

var str = NSString.stringWithCString("foo", encoding: NSUTF8StringEncoding)
var cs = str.UTF8String

Foundation 框架头文件已经在很多地方使用了instancetype,但不是 但在任何可能的地方(如buttonWithType:)。这可能会在 SDK 的未来版本。

【讨论】:

  • 按钮是class 方法吗?或者 UIButton 的 instance 是否等于 UIButton 的工厂方法/类方法之一?
  • @Honey: UIButton.buttonWithType(...) 是一个类方法(或者更好:在 Swift 1 中作为类方法)。
  • 我明白了那部分,但不要只是混淆了变异的东西是如何从类方法派生的,即实例。
【解决方案3】:

如果你 cmd 点击 buttonWithType 你会看到它在 swift 中被声明为

class func buttonWithType(buttonType: UIButtonType) -> AnyObject!

由于它返回的类型是AnyObject!您需要将其类型转换回 UIButton。

【讨论】:

  • 它实际上是一个可选的,它可以是 nil
  • 你是对的,我在考虑,将编辑我的帖子,感谢您的关注。
【解决方案4】:

现在是 Swift 2.1

var button = UIButton(type: .System)

因此无需使用 .buttonWithType 进行向下转换

【讨论】: