一、Swift的数据类型
Int是整型;
Double和Float是浮点型;
Bool是布尔型;
String是字符串;
Array和Dictionary是集合类型;
元组(Tuple);
可选(Optional)类型;
元组可以让你创建或者传递一组数据,比如作为函数的返回值时,你可以用一个元组可以返回多个值。
可选(Optional)类型,用于处理值缺失的情况。可选表示“那儿有一个值,并且它等于 x ”或者“那儿没有值”。可选有点像在Objective-C 中使用 nil,但是它可以用在任何类型上,不仅仅是类。可选类型比 Objective-C 中的 nil指针更加安全也更具表现力,它是 Swift 许多强大特性的重要组成部分。
Swift用字符串插值(string interpolation)的方式把常量名或者变量名当
做占位符加入到⻓长字符串中,Swift会⽤用当前常量或变量的值替换这些占位
符。将常量或变量名放⼊入反斜杠符加一对圆括号中 "\()":
整数边界
使用min或max值来获取该类型的最大最小值,如:
let minValue = UInt8.min // minValue is equal to 0, and
is of type UInt8 let maxValue = UInt8.max // maxValue is
equal to 255, and is of type UInt8 这些值边界值区分了整数
的类型(⽐比如 UInt8),所以可以像该类型的其他值⼀一样被⽤用在表达式中⽽而不
⽤用考虑益处的问题。
类型别名为现有类型定义的替代名称。您可以使用typealias关键字定义类型别名。当你使用的类型名称更符合上下文时,可以定义如:typealias AudioSample = UInt16
元组类型
元组类型可以将一些不同的数据类型组装成一个元素,这个元素可以用来作为函数的返回值返回包含多种数据类型的值。例:let http404Error = (404, "Not Found")
可选类型
在一个值可能不存在的时候,可以使用可选类型。这种类型的定
义是:要么存在这个值,且等于x,要么在这个值不存在。
使用断言调试
断言是一种实时检测条件是否为true的方法。如果这个条件为false,那么代码将会中断执行。
二、基本运算符
1、b为负值时的b的符号被忽略,这意味着%b和%-b的结果是
一样的。
println("-9 除 4 取余:\(-9%4)"); -à -9 除 4 取余:-1
println("-9 除 -4 取余:\(-9%(-4))"); -> -9 除 -4 取余:-1
不同于C和Objective-C,Swift的余数运算符也能运用于浮点数:
2、封闭范围运算符
封闭范围运算符(a…b)定义了一个范围,从a到b,并包括a和b的
值。
3、半封闭的区域运算符
半封闭的区域运算符(a..b)定义了从a到b的范围,但不包括b。
4、字符串通过isEmpty属性可以检查一个字符串是否为空
5、数组
a) 通过只读属性count来读取数组的长度;
b) 通过一个返回布尔类型的isEmpty属性检查数组的长度是否为0
c) 在数组末尾增加一个元素可以通过append方法
d) 甚至,还可以用(+=)操作符来把一个元素添加到数组末尾
e) 你也可以用(+=)操作符来把一个数组添加到另一个数组的末尾
f) 你可以使用下标语法一次性改变一系列的值,尽管修改的区域远远大于要修改的值。在下面的雷子中, 替换掉
“Chocolate Spread”, “Cheese”,”Butter”,”Bananas”,”Apples”:
shoppingList[4...6] = ["Bananas", "Apples"] // shoppingList 现在包含6个元素
g) 在一个特定的索引位置插入一个值,可以使用insert(atIndex:)方法shoppingList.insert("Maple Syrup", atIndex: 0)
h) 你可以调用removeAtIndex方法移除特定的元素。这个方法移除特定索引位置的元素,已经返回这个被移除的元素(尽管你并不关心这个返回值)。
i) 如果你从数组中移除最后一个元素,使用removeLast方法
j) 遍历数组
i. 可以使用for-in循环来遍历数组中的值
ii. 使用enumerate函数代替会更方便,enumerate函数对于每一个元素都会返回一个包含元素的索引和值的元组(tuple)。
例:for (index, value) in enumerate(shoppingList)
k) 你可以通过这个初始化方法增加一个新的数组,元素的数量成为count,合适的默认值为repeatedValue 例var threeDoubles = Double[](count: 3, repeatedValue: 0.0)
6、字典
a)
i. updateValue(forKey:) 方法去设置或者更新一个特定键的值、
ii. updateValue(forKey:) 方法如果键不存在则会设置它的值,如果键存在则会更新它的值, 和下标不一样是,
iii. updateValue(forKey:) 方法 如果更新时,会返回原来旧的值
a) removeValueForKey方法,这个方法如果存在键所对应的值,则移除一个键值对,并返回被移除的值,否则返回nil
b) 字典中的每一个元素都会返回一个元祖(tuple),你可以在循环部分分解这个元祖,并用临时变量或者常量来储存它。
例子:for (airportCode, airportName) in airports { println("\(airportCode): \(airportName)") }
注意Swift中的字典类型是非序列化集合
7、Where关键词
switch语句可以使用where关键词来增加判断的条件,在下面的例子中:
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint
{
case let (x, y) where x == y:
println("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
println("(\(x), \(y)) is on the line x == -y")
case let (x, y):
println("(\(x), \(y)) is just some arbitrary point")
}
每个case都因为有where而不同,第一个case就是判断x是
否与y相等,表示点在斜线y=x上。
8、控制跳转语句
在Swift中控制跳转语句有4种,让编程人员更好地控制代码的流转,包括:
continue
break
fallthrough
return
fallthrough
由于Swift中的switch语句不会自动的因为没有break而跳转
到下一个case,因此如果需要想C语言中那样,依次执行每个
case的时候,就需要用到fallthrough关键词。
三函数
函数的参数和返回值
多返回值函数
你可以使⽤用一个元组类型作为函数的返回类型返回一个有多个值组成
的一个复合作为返回值。
外部参数名
有时当你调⽤用一个函数将每个参数进⾏行命名是⾮非常有⽤用的,以表明你
传递给函数的每个参数的目的。
你写一个外部参数
名称在它所⽀支持的本地参数名称之前 ,之间⽤用一个空格来分隔:
Func someFunction(externalParameterName localParameterName: Int){
}
现在,您可以使⽤用这些外部参数名称调⽤用清楚明确的调⽤用该函数:
外部参数名称速记
如果你想为一个函数参数提供一个外部参数名,然而本地参数名已经
使用了一个合适的名称了,你不需要为该参数写相同的两次名称。取
⽽而代之的是,写⼀一次名字,并⽤用⼀一个 hash符号(#)作为名称的前
缀。这告诉Swift使⽤用该名称同时作为本地参数名称和外部参数名
称。
参数的默认值
可以为任何参数设定默认值来作为函数的定义的⼀一部分。如果默认值
已经定义,调⽤用函数时就可以省略该参数的传值。
可变形参
可通过在形参的类型名后边插入三个点符号(...)来编写可变形参。
注意:函数最多可以有一个可变形参,而且它必须出现在参数列表的最后,以避免使
用多个形参调用函数引发歧义。如果你的函数有一个或多个带有默认值的形参,并且
还有可变形参,请将可变形参放在所有默认形参之后,也就是的列表的最末尾。
输入-输出参数
如果你想有一个函数来修改参数的值,并且想让这些变化要坚持在函数调用结束后,你就
可以定义输入 -输出参数来代替。通过在其参数定义的开始添加inout关键字写用来标明输入 -输出参数。一个在输入 -输出参数都有一个传递给函数的值,由函数修改后,并从函数返回来替换原来的值。参数列表中只可以传递一个变量作为一个 in-‐out 参数。不能传递一个常数或常值作为参数,因为常量和⽂文字不能修改。你直接在变量名前放置一个连字符( &),当你把它作为一个参数传递给一个 in-‐out 参数,表明它可以通过该功能进⾏行修改。
使用函数类型
在 swift 中您可以像任何其他类型一样的使用函数类型。
func addTwoInts(a: Int, b: Int) -> Int {
return a + b
}
var mathFunction: (Int, Int) -> Int = addTwoInts
作为形参类型的函数类型
作为返回类型的函数类型
嵌套函数
嵌套函数默认对外界是隐藏的,但仍然可以通过它们包裹的函数调用和使用它。enclosing
function 也可以返回一个嵌套函数,以便在其他作用域中使用嵌套函数。
闭包
闭 包 是 功 能 性 自 包含 模块 , 可以 在代 码中 被传 递和 使用 。
在 函数 章节中介绍的全局和嵌套函数实际上也是特殊的闭包,闭包采取如下三 种形式之
一:
1. 全局函数是一个有名字但不会捕获任何值的闭包
2. 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
3. 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的没有名字的闭包
闭包的函数体部分由关键字 in 引⼊入。 该关键字表⽰示闭包的参数和返回值
类型定义已经完成,闭包函数体即将开始。
例:var result = sort(names,{(s1:String,s2:String) -> Bool in return s1 < s2})
根据上下⽂文推断类型:
例:var result1 = sort(names, { s1, s2 in return s1 > s2 } )
单⾏行表达式闭包可以省略 return
例:var result2 = sort(names, { s1, s2 in s1 > s2 } )
参数名称缩写
例:var result3 = sort(names, { $0 > $1 } )
运算符函数
例:var result4 = sort(names, >)
Trailing 闭包
reversed = sort(names) { $0 > $1 }
当闭包⾮非常长以⾄至于不能在⼀一⾏行中进⾏行书写时, Trailing 闭包变得⾮非常有
⽤用。
四、枚举
使⽤用 toRaw 和 fromRaw 函数可以转换原始值和枚举值。
if let convertedRank = Rank.fromRaw(3) {
let threeDescription =
convertedRank.simpleDescription()
}
五、类与结构
、结构和枚举类型是数值类型
类是引用类型
特征操作
因为类是引用类型,那么就可能存在多个常量或者变量只想同一个类
的实例(这对于数值类型的结构和枚举是不成立的)。
可以通过如下两个操作来判断两个常量或者变量是否引用的是同一个
类的实例:
相同的实例(===)
不同的实例(!==)
六、小结
1. 在十进制浮点数中通过大写或者小写的e来指定,在十六进制浮点数中通过大写或者小写的 p来指定。
2. 类型别名 (type aliases) 就是给现有类型定义另一个名字。你可以使用typealias关键字来定义类型别名。
3. Swift有两个布尔常量,true和false
4. 使用可选( optionals )来处理值可能缺失的情况。可选表示:有值,等于x
a) 或者 • 没有值
b) 使用 !来获取一个不存在的可选值会导致运行时错误。使用 !来强制解析值
之前,一定要确定可选包含一个非 nil的值。
5. 区间运算符
a) 闭区间运算符 a…b 定义一个包含从 a到b( 包括a和b) 的所有值的区间。
b) 半闭区间 a..b定义一个从 a到b但不包括b的区间
6. Swift 也提供恒等===和不恒等!==这两个比较符来判断两个对象是否引用
同一个对象实例。
7. isEmpty属性来判断该字符串是否为空
8. 一个函数至多能有一个可变参数,而且它必须是参数表中最后的一个。这样做是为了避免函数调用时出现歧义。
9. 输入输出参数
a) 当传入的参数作为输入输出参数时,需要在参数前加&符,表示这个值可以被函数修改。
b) 定义一个输入输出参数时,在参数定义前加inout关键字。一个输入输出参数有传入函数的值,这个值被函数修改,然后被传出函数,替换原来的值。
10. 初始化方法中参数会自动带入外部名、不用写在参数名称前添加#
11. 初始化方法的重载不需要加override 和 func
12. 在swift中,没有this, 这点需要注意
13. Is和as的区别 is 判断是否属于某类型 as把类型转换为某类型
14. 属性的Set方法中 newValue 表示赋值进来的值
15. 枚举
a) 使用 toRaw 和 fromRaw 函数来在原始值和枚举值之间进行转换。
b) Switch 中必须要写default
16. 类型别名(type aliases)就是给现有类型定义另一个名字。你可以使用 typealias 关键字来定义类型别名。
17. 何时使用断言当条件可能为假时使用断言,但是最终一定要保证条件为真,这样你的代码才能继续运行。
18. 字符串是值类型
Swift 的 String 类型是值类型。如果您创建了一个新的字符串值,那么当其进行常量、变量赋值操作或在函数/方法中传递时,会进行值拷贝。在不同情况下,都会对已有字符串值创建新副本,并对该新副本进行传递或赋值。
注意:和 Cocoa 中的 NSString 不同,当您在 Cocoa 中创建了一个 NSString 实例,并将其传递给一个函数/方法,或者赋给一个变量,您永远都是传递或赋值同一个
NSString 实例的一个引用。除非您特别要求其进行值拷贝,否则字符串不会进行赋值
新副本操作。
19. 计算字符数量通过调用全局 countElements 函数,并将字符串作为参数进行传递可以获取该字符串的字符数量。
七、方法( Methods )
1、有时为方法的第一个参数提供一个外部参数名称是非常有用的,尽管这不
是默认的行为。你可以自己添加一个显式的外部名称或者用一个井号
(#)作为第一个参数的前缀来把这个局部名称当作外部名称使用。
相反,如果你不想为方法的第二个及后续的参数提供一个外部名称,可以
通过使用下划线(_)作为该参数的显式外部名称,这样做将覆盖默认行
为。
2、如果你确实需要在某个具体的⽅方法中修改结构体或者枚举的属性,
你可以选择 变异(mutating)这个⽅方法,然后⽅方法就可以从⽅方法内部改变
它的属性;并且它做的任何改变在⽅方法结束时还会保留在原始结构中。
3、声明类的类型方法,在方法的 func关键字之前加上关键字class;声明结构体和枚举的类型方法,在方法的func关键字之前加上关键字static。
八、附属脚本语法
1、 定义附属脚本使用 subscript关键字,显式声明入参(一个或多个)和返回类型
2、 附属脚本可以设定为读写或只读
九、接口和扩展
1、 使用 protocol 来声明一个接口。
2、 类、枚举和结构体都可以实现接口。
3、 使用 extension 来为现有的类型添加功能,比如添加一个计算属性的方法。你可以使用扩展来给任意类型添加协议,甚至是你从外部库或者框架中导入的类型。
十、泛型
1、 在尖括号里写一个名字来创建一个泛型函数或者类型。
2、 在类型名后面使用 where 来指定一个需求列表
func anyCommonElements <T, U where T: Sequence, U: Sequence, T.Generat
orType.Element: Equatable, T.GeneratorType.Element == U.GeneratorType.
Element> (lhs: T, rhs: U) -> Bool {
for lhsItem in lhs {
for rhsItem in rhs {
if lhsItem == rhsItem {
return true
}
}
}
return false
}
anyCommonElements([1, 2, 3], [3])
十一、OC与swift的相互调用
1、 swift调用oc
将 Objective-C 导入 Swift
要在同一个 app target 中导入 Objective-C 文件供 Swift 使用,你需要依赖 Objective-C的
桥接头文件(Objective-C bridging header)来暴露给 Swift。当你添加 Swift 文件到现有
的 Objective-C 应用时,Xcode 会自动创建这些头文件,反之亦然。
如果你同意,Xcode 会在源文件创建的同时生成头文件,并用 product 的模块名加上
-Bridging-Header.h 命名。
在 Build Settings 中,确保 Objective-C 桥接头文件的 build setting 是基于 Swfit 编译器,
即 Code Generation 含有头文件的路径。这个路径必须是头文件自身的路径,而不是它所
在的目录。
然后在桥接头文件中,加入oc的头文件,在swift中即可饮用oc的类
2、 oc调用swift
1、确保将框架 target 的 Build Settings > Packaging > Defines Module 设置为 Yes
2、在修改在 build setting 中的 Product Module Name 即可。
之后的项目会自动生成swift的头文件,头文件名称为Product Module Name-Swift.h
所有的swift都会在这个头文件里