Swift开发指南:使用Swift与Cocoa和Objective-C(Swift 4) - 2.互通性

章节导航:
Swift开发指南:使用Swift与Cocoa和Objective-C(Swift 4) - 1.入门
Swift开发指南:使用Swift与Cocoa和Objective-C(Swift 4) - 2.互通性


与Objective-C API进行交互

互操作性是能够在任何一个方向上与Swift和Objective-C进行接口,让您访问并使用以其他语言的文件中的一些代码。当您开始将Swift集成到应用程序开发工作流程中时,了解如何利用互操作性来重新定义、改进和增强编写Cocoa应用程序的方式是一个好主意。

互操作性的一个重要特点是,它可以让您在编写Swift代码时使用Objective-C API。导入Objective-C框架后,您可以实例化类,并使用本地Swift语法与它们进行交互。

初始化

要在Swift中实例化一个Objective-C类,可以使用Swift构造器语法调用其中的一个构造方法。

Objective-C构造方法以init开始,如果构造方法需要一个或多个参数则使用initWith:。当由Swift导入Objective-C初始化程序时,该init前缀将成为一个init关键字,表示该方法是Swift初始化程序。如果构造方法接受参数,则将其With移除,并将构造器其余部分对应地分割为命名了的参数。

参照以下Objective-C构造器

- (instancetype)init;
- (instancetype)initWithFrame:(CGRect)frame
           style:(UITableViewStyle)style;

以下是Swift构造器的声明:

init() { /* … */ }
init(frame: CGRect, style: UITableViewStyle) { /* … */ }

在实例化对象时,Objective-C和Swift语法之间的区别更为明显。

在Objective-C中,您可以执行以下操作:

UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];

在Swift,你这样做:

let myTableView: UITableView = UITableView(frame: .zero, style: .grouped)

请注意,您不需要调用alloc; Swift为您处理这个。还要注意,在调用Swift形式的构造方法时,init不会出现在任何地方。

您可以在指定常量或变量时显式提供类型,或者您可以省略类型,并且Swift会从构造方法自动推断类型。

let myTextField = UITextField(frame: CGRect(x: 0.0, y: 0.0, width: 200.0, height: 40.0))

这些UITableViewUITextField对象是您在Objective-C中实例化的对象。您可以以与Objective-C中相同的方式使用它们,访问任何属性并调用其各自类型上定义的任何方法。


类初始化方法和便利构造器

为了一致性和简单性,在Swift中,Objective-C类初始化方法作为便利构造器导入。这允许它们与构造器使用相同的语法。

例如,在Objective-C中,你可以这样调用这个初始化方法:

UIColor *color = [UIColor colorWithRed:0.5 green:0.0 blue:0.5 alpha:1.0];

在Swift中,你这样调用:

let color = UIColor(red: 0.5, green: 0.0, blue: 0.5, alpha: 1.0)


可失败构造器

在Objective-C中,构造器直接返回它们初始化的对象。要在初始化失败时通知调用者,Objective-C构造器可以返回nil。在Swift中,此模式内置于称为可失败构造器的语言功能中。

系统框架中的许多Objective-C初始化程序已被审计,可指示构造是否可以失败。您可以在你的Objective-C类中使用nullability annotations指出构造方法是否可以失败,如可空性和可选项章节所述。Objective-C构造器导入为init(...)如果构造不会失败,导入为init?(...)如果会失败。否则,构造器将被导入为init!(...)

例如,如果在提供的路径上不存在图像文件,则UIImage(contentsOfFile:)初始化程序可能无法初始化UIImage对象。如果初始化成功,您可以使用可选项绑定来打开可用构造器的结果。

if let image = UIImage(contentsOfFile: “MyImage.png”) {
    // loaded the image successfully
} else {
   // could not load the image
}
<br>

访问属性

使用@property语法的Objective-C属性声明将以以下列方式导入为Swift属性:

  • 具有可空属性属性(nonnullnullablenullresettable)的属性作为Swift属性导入,具有可选或非可选类型,如可空项和可选项所述。
  • 具有readonly属性属性的属性将导入为具有getter({ get })的Swift计算属性。
  • 具有weak属性属性的属性将导入为标有weak关键字(weak var)的Swift属性。
  • weak外与所有权有关的属性(即,assigncopystrong,或unsafe_unretained)被导入为合适的Swift属性存储。
  • class属性导入为Swift类型属性。
  • 原子属性(atomicnonatomic)不会反映在相应的Swift属性声明中,但是从Swift访问导入的属性时,Objective-C实现的原子属性仍然保持不变。
  • Swift忽略 Accessor属性(getter=setter=)。

您可以使用点语法访问Swift中的Objective-C对象上的属性,使用不带括号的属性名称。

例如,您可以使用以下代码设置对象的属性textColortext属性UITextField

myTextField.textColor = .darkGray
myTextField.text = “Hello world”

返回值并且不带参数的Objective-C方法可以像使用点语法的Objective-C属性一样调用。但是,由Swift作为实例方法导入,因为只有Objective-C @property声明由Swift作为属性导入。方法被导入并按照“ 使用方法”章节中的描述进行调用。


使用方法

您可以使用点语法从Swift调用Objective-C方法。

当将Objective-C方法导入到Swift中时,Objective-C选择器的第一部分将成为基本方法名称,并显示在括号之前。第一个参数立即出现在括号内,没有名称。选择的其余部分对应于参数名称,并显示在括号内。调用时需要所有选择器对应的参数。

例如,在Objective-C中,你可以这样做:

[myTableView insertSubview:mySubview atIndex:2];

在Swift,你这样做:

myTableView.insertSubview(mySubview, at: 2)

如果您调用一个没有参数的方法,那么还必须包含括号。

myTableView.layoutIfNeeded()



id兼容性

Objective-C id类型被Swift导入为Any。在编译时和运行时,当Swift值或对象作为id参数传入Objective-C时,编译器将引入通用桥接转换操作。当id值导入Swift时成为Any,运行时会自动处理桥接到类引用或Swift值类型。

var x: Any = “hello” as String
x as? String // String with value “hello”
x as? NSString // NSString with value “hello”

x = “goodbye” as NSString
x as? String // String with value “goodbye”
x as? NSString // NSString with value “goodbye

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值