互用性(互操作性)使开发者可以定义融合了 objective-c 语言特性的swift类。编写 swift 类时,不仅可以继承 objective-c 语言编写的父类,采用 objective-c 的协议,还可以利用 objective-c 的一些其它功能。这意味着,开发者可以基于 objective-c 中已有的熟悉、可靠的类、方法和框架来创建 swift 类,并结合 swift 提供的现代化和更有效的语言特点对其进行优化。
继承objective-c的类
在 swift 中,开发者可以定义一个子类,该子类继承自使用 objective-c 编写的类。创建该子类的方法是,在 swift 的类名后面加上一个冒号(:),冒号后面跟上 objective-c 的类名。
// swift
import uikit
class myswiftviewcontroller: uiviewcontroller {
// 定义类
}
开发者能够从 objective-c 的父类中继承所有的功能。如果开发者要覆盖父类中的方法,不要忘记使用override关键字。
采用协议
在 swift 中,开发者可以采用 objective-c 中定义好的协议。和 swift 协议一样,所有 objective-c 协议都写在一个用逗号隔开的列表中,跟在所在类的父类名后面(如果它有父类的话)。
// swift
class myswiftviewcontroller: uiviewcontroller, uitableviewdelegate, uitableviewdatasource {
// 定义类
}
objective-c 协议与 swift 协议使用上是一致的。如果开发者想在 swift 代码中引用 uitableviewdelegate协议,可以直接使用uitableviewdelegate(跟在 objective-c 中引用id
编写构造器和析构器
swift 的编译器确保在初始化时,构造器不允许类里有任何未初始化的属性,这样做能够增加代码的安全性和可预测性。另外,与 objective-c 语言不同,swift 不提供单独的内存分配方法供开发者调用。当你使用原生的 swift 初始化方法时(即使是和 objective-c 类协作),swift 会将 objective-c 的初始化方法转换为 swift 的初始化方法。关于如何实现开发者自定义构造器的更多信息,请查看构造器。
当开发者希望在类被释放前,执行额外的清理工作时,需要执行一个析构过程来代替dealloc方法。在实例被释放前,swift 会自动调用析构器来执行析构过程。swift 调用完子类的析构器后,会自动调用父类的析构器。当开发者使用 objective-c 类或者是继承自 objective-c 类的 swift 类时,swift 也会自动为开发者调用这个类的父类里的dealloc方法。关于如何实现开发者自定义析构器的更多信息,请查看析构器。
集成interface builder
swift 编译器包含一些属性,使得开发者的 swift 类集成了 interface builder 里的一些特色功能。和 objective-c 里一样,你能在 swift 里面使用 outlets,actions 和实时渲染(live rendering)。
使用outlets和action
使用 outlets 和 action 可以连接源代码和 interface builder 的 ui 对象。在swift里面使用 outlets 和 action,需要在属性和方法声明前插入@iboutlet或者@ibaction关键字。声明一个 outlet集合同样是用@iboutlet属性,即为类型指定一个数组。
当开发者在 swift 里面声明了一个 outlet 时,swift 编译器会自动将该类型转换为弱(weak)、隐式(implicitly)、未包装(unwrapped)的 optional(object-c里面对应指针类型)数据类型,并为它分配一个初始化的空值nil。实际上,编译器使用@iboutlet weak var name: type! = nil来代替 @iboutlet var name: type。编译器将该类型转换成了弱(weak)、隐式(implicitly)、未包装(unwrapped)的 optional 类型,因此开发者就不需要在构造器中为该类型分配一个初始值了。当开发者从故事板(storyboard)或者xib文件里面初始化对象 class 后,定义好的 outlet 和这些对象连接在一起了,所以,这些 outlet 是隐式的,未包装的。由于创建的 outlets 一般都是弱关系,因此默认 outlets 是弱类型。
例如,下面的 swift 代码声明了一个拥有 outlet、outlets 集合和 action 的类:
// swift
class myviewcontroller: uiviewcontroller {
@iboutlet var button: uibutton
@iboutlet var textfields: uitextfield[]
@ibaction func buttontapped(anyobject) {
println("button tapped!")
}
}
在buttontapped方法中,消息发送者的信息没有被使用,因此可以省略该方法的参数名。
实时渲染(live rendering)
开发者可以在interface builder中用@ibdesignable和@ibinspectable来创建生动、可交互的自定义视图(view)。开发者继承uiview或者nsview来自定义一个视图(view)时,可以在类声明前添加@ibdesignable属性。当你在 interface builder 里添加了自定义的视图后(在监视器面板的自定义视图类中进行设置),interface builder 将在画布上渲染你自定义的视图。
注意:只能针对框架里对象进行实时渲染
你也可以将@ibinspectable属性添加到和用户定义的运行时属性兼容的类型属性里。这样,当开发者将自定义的视图添加到 interface builder 里后,就可以在监视器面板中编辑这些属性。
// swift
@ibdesignable
class mycustomview: uiview {
@ibinspectable var textcolor: uicolor
@ibinspectable var iconheight: cgfloat
/* ... */
}
指明属性特性
在 objective-c 中,属性通常都有一组特性(attributes)说明来指明该属性的一些附加信息。在 swift 中,开发者可以通过不同的方法来指明属性的这些特性。
强类型和弱类型
swift 里属性默认都是强类型的。使用weak关键字修饰一个属性,能指明其对象存储时是一个弱引用。该关键字仅能修饰 optional 对象类型。更多的信息,请查阅特性。
读/写和只读
在 swift 中,没有readwrite和readonly特性。当声明一个存储型属性时,使用let修饰其为只读;使用var修饰其为可读/写。当声明一个计算型属性时,为其提供一个 getter 方法,使其成为只读的;提供 getter 方法和 setter 方法,使其成为可读/写的。更多信息,请查阅属性。
拷贝
在 swift 中,objective-c 的copy特性被转换为@nscopying属性。这一类的属性必须遵守 nscopying协议。更多信息,请查阅特性。
实现core data managed object子类
core data 提供了基本存储和实现nsmanagedobject子类的一组属性。在 core data 模型中,与管理对象子类相关的特性或者关系的每个属性定义之前,将@nsmanaged特性加入。与 objective-c 里面的 @dynamic特性类似,@nsmanaged特性告知 swift 编译器,这个属性的存储和实现将在运行时完成。但是,与@dynamic不同的是,@nsmanaged特性仅在 core data 支持中可用。