-
swift 中所有的数据类型都是由三种不同的数据结构(枚举、结构体、类)中的某一种实现的。
-
枚举和结构体在代码中以值得方式进行传递,类是通过引用的方式进行传递的。
-
基本数据类型都是基于结构体实现的,它们可能会通过属性或方法实现一些额外的功能
-
swift 是一门强类型语言,意味着每一个变量类型在编译时期就已经确定,并且在其生命周期中只能春初固定类型的值
-
变量的声明
var itemCount: Int = 0
只要在读取变量之前设置初始值即可 -
swift中有一个功能叫做类型推断,如果编译器能够从初始值中获取到足够多的信息来推断类型,那么在声明时可省略类型,如
var itemCount = 0
-
字符串插值可将变量、常量和其他表达式的值添加到字符串中,在括号中包含一个变量或表达式,再用一个反斜杠\进行转义,最后直接添加到字符串中。如:
var itemCount = 34 print("there are \(itemCount) items")
-
if 和 for 可省略检测表达式中的括号
-
区间表达式
for i in 0 ..< 10 {} for i in 0 ... 10 {}
-
如果要将某种类型转化为另一种类型,可以创建一个新的所期望的实例,然后用初始值设置这个新实例的初始值
var a: Int32 = 10 var b: Int64 = Int64(a)
-
小数可以使用Float 和 Double 类型,Float是32位的,Double 是64位的,这与设备的架构无关。如果未指定类型,编译器总推断为Double类型。
-
布尔型,swift只有表达式显示返回一个布尔型才能被用于布尔值的声明。
-
字符串,只需简单的置于双引号内。String是Character类型值得集合,每个Character就是一个Unicode字符。 String使用count()函数来判断一个字符串中有多少个字符。可以使用“+”运算符将字符串拼接起来,也可以使用“+=”运算符将一个字符串拼接到另一个字符串中。可以直接使用“==”来判断两个字符串是否相等。
-
数组 swift中数组是集合类型中的一种,用来存储相同类型的有序列表。声明数组时,必须指定数组包含的类型,一旦确定类型,就只能存储这一类型的数据。swift中可以把结构体、枚举、类添加到数组中,由于所有基本数据类型都是用结构体实现的,所以他们都可以放到数组中。
-
可空类型使程序员不得不考虑什么时候值可能为空,并且强制规定不予许用普通的类型存储空值。
if let someValue = someOptional { // 合并了非空判断和拆箱 // 正常使用someValue }
-
闭包表达式
{(parameters) -> returnType in statements }
-
如果元组中的某个值你不需要,再分解时你可以用“_”替代,再分解时编译器会忽略该值。
let a = (1, "dfg", "swe") let (_, charater, _) = a ---> charater: String = "dfg"
-
swift 中的 switch 语句没有了break 可以用fallthrough 穿越,case不仅可以匹配值,也可以匹配范围、模式并进行值绑定。
-
枚举
enum NetworkConnection { case NotConnection case WiFi case Cellular } var b = NetworkConnection.WiFi b = .Cellular // 推断出b的类型之后,就可用省略类型的点标记法来更新变量值
-
在使用这个类的实例前,你必须初始化所有属性。其中有默认值的属性会被自动初始化,没有默认值的必须在
init()
方法中设置初始值 -
init()
方法有特殊的权限,能在实例中设置或改变常量属性,甚至能在同一个init()
方法中进行多次设置或改变。在init()
方法返回或完成之前,常量属性都还没有被锁定。 -
能够完全初始化对象的
init()
方法叫做指定初始化函数,依赖其他方法初始化对象的init()
方法叫做便捷初始化函数。我们通过使用convenient
关键字来声明一个便捷初始化函数。 -
当继承起作用时,初始化变得稍微有些复杂。当一个类继承父类,他可能继承也可能不继承
init()
方法。①如果子类提供自己的指定初始化函数,他将不继承任何父类的init()
方法。②如果子类只提供便捷初始化函数或者不提供init()
方法,它将继承父类中所有init()
方法。这是swift的部分安全特性。 -
存储型属性通过附加在类实例中的变量来体现,可以简单的以
var
let
声明,并且赋予默认值或在对象实例化时初始化。 -
计算型属性没有相关联的变量,因此并不直接存储任何数据。他们被间接访问或计算类中的其他数据。可以通过声明一个setter 和 getter 方法来使用计算型属性:
// 计算型属性(只读属性) var largePictureURLs: [NSURL]? { return retweeted_status == nil ? storeLargePictureURLs : retweeted_status?.storeLargePictureURLs } // 计算型属性 (非只读属性) var d: Int { get { return a + b } set { a = newValue } }
-
属性观察者
var source: String? { didSet { // 重新计算来源并且保存 // 在 didSet 中,给 source 再次设置值,不会调用 didSet source = "来自于 " + (source?.cz_href()?.text ?? "") } }
-
延迟属性,当一个对象实例化时,其所有属性都必须被初始化,这样做开销可能非常大或根本不需要。swift引入了
lazy
关键字,如果在一个属性开头加上lazy
关键字,编译器就不强制初始化该属性,并将其初始化推迟至属性的第一次使用时。lazy var logo: UIImage = { let data = try! Data(contentsOf: URL(fileURLWithPath: "cache/xixi.png")) let image = UIImage.init(data: data, scale: 0.8) return image! }()
-
协议
/// 微博 Cell 的协议 /// 如果需要设置可选协议方法 /// - 需要遵守 NSObjectProtocol 协议 /// - 协议需要是 @objc 的 /// - 方法需要 @objc optional @objc protocol WBStatusCellDelegate: NSObjectProtocol { /// 微博 Cell 选中 URL 字符串 @objc optional func statusCellDidSelectedURLString(cell: WBStatusCell, urlString: String) }
-
访问控制,public 是最高一级,标记为public的实体可被同模块中的任何文件使用,或被引用了该模块的其他模块中的任何文件使用。internal 是默认级别,internal实体可被同模块中的任何文件使用。private是最低一级,private实体仅在其被定义的代码段中可用。
-
swift 中可空类型,swift的类型系统消除了为空的混乱情况,强制使用
nil
来代表无效值,同时明确规定,只有可空类型允许存储nil值。 -
可控绑定
if let w = f { print(w) }
-
强制拆箱
var a: Int? = 3 let b = a!
-
可空链
let innerString = outer.inner?.innerInner?.innerMostStr?
可空链的语法类似于强制拆箱,只不过用?代替了!,语法被简化的同时保证了可控类型的安全使用。在可空链的每一个节点上,节点的可空值都会被检测,只有在值存在的情况下,下一步操作才会继续执行。如果任何一个节点返回nil,则整个可空链返回nil,当然可空链也会带来一个负面效应,如果最后一步操作返回的是非可空值,他也会被隐式的包装为可空类型。
-
带隐式拆箱的可空
数据在某些情况下具备这样一个特点,它们一旦初始化(一般此类数据会被延迟初始化)之后就不会为空。而因为初始化之前它们有可能为空,我们不便用非可空类型存储它们。如果用可空类型定义的话,又不想在初始化之后每次都进行非空检查,对于这样的情况swift 提供了“带隐式拆箱的可空类型”。
可空类型和带隐式拆箱的可控类型不同之处在于二者的定义方法和访问方法。但是在可控绑定方面,二者是一致的。如下创建(用!取代?):
var implicitlyUnwrapped: String!
尽管带隐式拆箱的可空在许多方面和标准和标准的可空是一样的,但前者和后者是不同的enum 类型,这两个enum类型不能对接。 因为带隐式拆箱的可空总是被假定是有值的,因此在访问他们时,不需要进行强制拆箱。
带隐式拆箱的可空类型要求开发者自己确保值总是有效的,如果你不为它指定一个值,那么在使用带隐式拆箱的可空时将会引起错误。 其在处理依赖对象的初始化时用的最多。 你应该在一旦初始化即可保证有值的对象上使用带隐式拆箱的可空类型,如果这个对象有可能被改变为nil,你应当使用标准的可空类型。
-
泛型
编写代码时,对象实例的类型是不可知的,在使用时才指定实际的类型。使用泛型编程,通过将功能从具体的类型中抽象出来,可以为函数或数据类型创建通用的模板。它在swift中是一个关键的概念。使用泛型使得你通过定义需要的数据种类以及编译器自动创建特定类型的代码,从而专注于如何与数据交互。 泛型函数提供了原型功能定义,(编译器可以)按需构造众多的重载函数,这种构造是自动的。 泛型函数的声明与普通函数的声明类似,只需要额外加入一列类型参数。
func isASubclassOfNSObject<T>(objectToTest:T) -> Bool { return objectToTest is NSObject }
-
函数
func sayHello(number: Int, word: String) { print("hello") }
这个例子中函数的参数只有本地参数名,本地参数名用于在函数体中使用传入的参数值,同时这个本地参数名对于调用者是无效的。但是为了让函数的调用者明白参数的具体含义,并让调用者根据名称而不是顺序来传参,会添加额外的参数名叫做外部参数名。外部参数名放在本地参数名之前
func sayHello(number: Int, withWord word: String) { print("hello") }
如果你想忽略成员函数的外部参数名,则用“_”作为参数的外部参数名即可。
-
参数的默认值
swift允许为参数指定默认值。如果调用时缺省某个参数,那么函数会使用该参数的默认值进行调用。要定义参数默认值,在参数类型声明后使用“=”即可
func hah(i: Int = 4, numbers: Int...) -> Int { var max = i for number in numbers { if number > max { max = number } } return max }
调用:
let b = hah(numbers: 12,34,5)
-
可变参数
允许函数接收0或多个值作为参数,其需要在参数类型后加上“…”,在函数体内部可变参数被视为同一类型的数组,如上边的例子,一个函数只能定义一个可变参数,同时可变参数只能是函数的最后一个参数。
-
inout参数
允许函数直接改变外部传入的参数值。func hah(a: Int, b: inout Int) -> Int { b += a return b }
var f = 7 let c = hah(a: 3, b: &f) print(c, f)
-
返回类型
如果定义函数时没有返回值,这个函数仍然会有一个返回类型:()。如果一个函数既没有参数有没有返回值,这个函数的类型为:( ) -> ( )。元祖作为函数返回值:
func processNumbers(array: [Int]) -> (sum: Int, max: Int) { var sum = 0 var max = Int.min for i in array { sum += i if i > max { max = i } } return (sum, max) }
-
闭包
闭包的好处在于不用命名和声明函数就能在代码段中使用参数并返回值,同时可以像函数一样,用函数作为参数或返回值。
闭包作为函数参数
let numbers = [2, 6, 7, 2, 9] let abc = numbers.sorted { (a: Int, b: Int) -> Bool in return a > b }
参数及返回值的类型推断
由于在函数声明时,参数和返回值类型都是事先声明的,因此闭包的类型信息可以从中推断,我们可以忽略闭包中的类型信息:
let numbers = [2, 6, 7, 2, 9] let abc = numbers.sorted { a, b in return a > b }
通常闭包都会有一个返回值,因此当闭包仅由一条return 语句构成时,return 关键字可以省略
let numbers = [2, 6, 7, 2, 9] let abc = numbers.sorted { a, b in a > b}
闭包参数自动含有另外一种形式的参数名,例如$0、$1、$2······,根据参数的顺序依次递增,你可以不提供参数名列表,而直接使用这种按序号命名的参数名
let numbers = [2, 6, 7, 2, 9] let abc = numbers.sorted { $0 > &1 }
总结
let numbers = [2, 6, 7, 2, 9] let abc = numbers.sorted { (a: Int, b: Int) -> Bool in // 常规 return a > b } let abb = numbers.sorted { a, b in // 省略类型 return a > b } let aaa = numbers.sorted { a, b in a > b } // 省略return let bbb = numbers.sorted { $0 > $1} // 闭包按序号命名的参数名
-
尾随闭包
有些函数最后一个参数往往使用了函数类型,swift为它提供了一种简化的写法:尾随闭包。它将参数中的最后一个闭包写在参数列表之后, 如果函数参数中只有一个闭包参数的话,圆括号是可选的,可以像上面一样忽略
网友评论