Everrthing is an Object? In swift, "everything is an object." That's a boast common to various modern object-oriented languages, but what does it mean? In Swift object type are declared with the flavor of the object type(enum, struct or class). 进入正题,class是引用类型,定义如下: 一.类定义
class Swifter: NSObject {
// 声明存储属性
let id = "Swift"
var name:String
var age:Int
var bodyWeight: Float
var foodWeight: Float?
// 构造器 指定构造器 required修饰构造器 可失败的构造器 以及遍历构造器
init(_ name:String, setAge age: Int, body bodyWeight: Float) {
self.name = name
self.age = age
self.bodyWeight = bodyWeight
super.init()
}
// required修饰的构造器 注意 不是required修饰的构造器就一定要实现
/**
如果子类不指定任何自己的构造器,直接继承父类的构造器时,不必再实现父类required修饰的构造器
如果子类实现了自己的构造器(或者显示override父类的某个指定构造器),就必须实现重写required修饰的构造器
*/
required init(name: String, age:Int, bodyWeight: Float) {
self.name = name
self.age = age
self.bodyWeight = bodyWeight
super.init()
}
// 可失败的构造器
/**
实际上就是提供一个返回nil的条件让构造器初始化失败
*/
init?(_ name:String,setAgeOrInvalid age:Int, body bodyWeight: Float) {
if age < 0 || age> 150 { // age < 0 , age > 150 <=> age <0 && age > 150
return nil
}
self.name = name
self.age =age
self.bodyWeight = bodyWeight
}
// 便利构造器
/**
关键字 convenience
Convenience initializer
A convenience initializer is marked with the keyword convenience.
It is a delegating intializer; it must contain the phrase self.init(...).
Moreover, a convience initializer must ultimately delegate to a designated initializer:
when it says self.init(...), it must call a designated initializer in the same class --
or, if it calls another convenience initializer in the same calss, the chain of convenience
initializers must end by calling a designated initializer in the same class.
简单总结就是便利构造器最终会调用指定构造器,可以用来封装底层构造器收缩参数列表
*/
convenience init(_ name: String) {
self.init(name: name, age: 11, body: 10)
}
// 可失败的便利构造器
convenience init?(theName name: String)
let localName = name as NSString
if localName.length == 0 {
return nil
}
self.init(name,setAge: 10, body: 11 )
}
// 析构器
/**
析构器:与它成对应关系的就是构造器,析构用来在对象释放的时候提供一个操作的时机
*/
// 对象函数,类函数,静态函数不是当前讨论重点省略
总结:
1.一个class类中可以由属性(存储/静态也可以使用lazy或者static修饰)、构造器(便利构造器、指定构造器、)、函数(类函数、对象函数、静态函数、下标函数)、析构器组成。
构造器的规则: 如果子类有自己指定的构造器,就必须实现父类required修饰的指定构造器; 如果子类没有自己的构造器,就直接继承父类的构造器不用重写父类required 修饰的构造器。 便利构造器: keyWord关键字convenience,本质上便利构造器调用某个指定构造器,便利构造器的优点是压缩参数列表。
析构器:与构造器对应,释放对象的时候调用
2.存在继承关系
3.修改属性的函数不用mutating关键字修饰
4.存放在堆区
二.类的生命周期 iOS开发的语言不管是OC还是Swift后端都是通过LLVM进行编译的,如下图所示:
OC通过clang编译器编译成IR,然后再生成可执行文件.o(机器码)。 Swift通过Swift编译器编译成IR然后生成可执行文件。
添加target增加脚本如图:
生成一个ViewController.sil文件,摘抄部分主要内容
class Swifter {
@_hasStorage @_hasInitialValue final let id: String { get }
@_hasStorage var name: String { get set }
@_hasStorage var age: Int { get set }
@_hasStorage @_hasInitialValue var bodyWeight: Float? { get set }
@_hasStorage @_hasInitialValue var data: Data? { get set }
init(_ name: String, setAge age: Int)
required init(name: String, age: Int)
init?(_ name: String, setAgeOrInvalid age: Int)
convenience init(_ name: String)
convenience init?(theName name: String)
func objFunction()
class func clsFunction()
final func doNotPermissionOverride()
static func staticFunction()
@objc deinit
}
对应上面Swifter类的声明逐行解读: 首先存储属性,let定义的属性变量解析出来实际上就是get属性;var定义的属性变量解析出来就是get-set属性。指定构造器、便利构造器以及可失败的构造器与Swift雷同。定义的对象方法、类方法也容易识别。稍微注意一点的就是析构器使用了@objc修饰,这个修饰词的作用就是:
1.当Swift需要使用OC的语言特性时,例如当需要声明协议中的可选方法和可选属性时。
2.当需要发送潜在的消息给AnyObject对象的时候可以使用(该对象没有@objc修饰的属性或者函数,可以在一定程度上不抛出异常)。举例:
3.当Swift需要暴露给OC代码时使用@objc标记。例如将Swift的enum暴露给Objective-C使用。关于@objc的其他操作会择日进行全部阐述。
二.结构体
struct Swifter {
let id = "Swift"
var name:String
var age:Int
var bodyWeight: Float
var foodWeight: Float?
// 1.构造器隐式实现
//init(...){
// 构造器自动生成
//}
// 导致结构体对象重新创建添加mutating关键字修饰
mutating func changeProtperty(newAge new:Int)-> Void {
self.age = new
}
//下标函数(class类型同理)
// 下标函数 在非枚举类型使用的时候 可以用来获取成员属性的某个部分
subscript(index: Int)-> String {
get {
let str = self.id
return index < (str as NSString).length && index >= 0 ? String(str[str.index(s.startIndex,offsetBy: Index)]) : String("越界")
}
}
}
// 调用下标函数 引用类型不再赘述
let swifter: Swifter = Swifter.init(name: "Nicole",age: 12, weight: 10, foodWeight: 2)
let str = swifter[0] // “S”
总结:
1.结构体构造器可以隐式实现(和class的主要区别)
2.不存在继承关系(和class的主要区别)
3.成员属性被修改时(值类型属性更改以及引用类型属性地址改变)会重新创建新的结构体对象
4.函数更改成员导致需要重新创建结构体对象时,该函数使用mutating修饰
5.存放在栈区