switch(元组)
-
特点
- 其他语言中的switch语句只能比较离散的整形数据(字符可以转换成整数)
- 但是swift中可以比较整数、浮点数、字符、字符串、和元组数据类型,而且它可以是离散的也可以使连续的范围
- 而且在swift中case语句不需要显示的添加break语句,分支语句会自动进行跳转
- 每个switch语句至少有一个default语句
-
switch中比较元组
- 可以在元组中进行值绑定,来对某一个值进行判断
- 可以使用where 语句对元组中的条件进行判断
跳转语句
- break、contune、fallthrough、return
break
-
主要用户循环体中终止循环
-
break的使用有两种方式
break // 没有标签
break label // 添加标签
// break语句中标签的使用
label1: for var x = 0; x < 5; x++ { // 标签1
label2: for var y = 0; y > 0; y-- { // 标签2
if x == y {
break label1 // 默认是跳出标签2,加上标签,可以直接跳出到指定循环
}
print("(x,y) = (\(x),\(y))")
}
}
continue
-
continue 的使用和break类似,可以使用标签指定继续的循环
// continue语句中标签的使用
label1: for var x = 0; x < 5; x++ { // 标签1
label2: for var y = 0; y > 0; y-- { // 标签2
if x == y {
continue label1 // 默认是跳出标签2,加上标签,可以直接跳出到指定循环
}
print("(x,y) = (\(x),\(y))")
}
}
fallthrough
- fallthrough是贯通语句,在swift的swiftch语句中case语句不能贯通,但是如果我们需要设置贯通语句,可以使用fallthrough语句
- 在switch语句中case后fallthrough,会执行下一个case语句
函数
-
参数传递
- 外部参数名和内部参数名
- 外部参数名可以在调用函数时显示出来
func rectangle(W width:Int, H height:Int) -> Int {
// 其中W\H是外部参数名,在外部调用这个方法时会显示出来,提示这个参数是神马意思
// width\height 是内部参数,在函数内部调用使用
return width * height
}
- 也可以让内部便令名变为外部变量名,使用字符 “#”
func rectangle(#width:Int, #height:Int) -> Int{
// 其中W\H是外部参数名,在外部调用这个方法时会显示出来,提示这个参数是神马意思
// width\height 是内部参数,在函数内部调用使用
return width * height
}
-
参数默认值
func rectangle(#width:Int = 100, #height:Int = 100) -> Int {
// 其中W\H是外部参数名,在外部调用这个方法时会显示出来,提示这个参数是神马意思
// width\height 是内部参数,在函数内部调用使用
return width * height
}
-
可变参数
func sum(numbers: Double... ) -> Double {
var total: Double = 0
for num in numbers {
total += num
}
return total
}
-
参数的引用传递
- 在众多数据类型中,只有类是引用传递,其他的数据类型如整形、浮点型、布尔型、字符串、元组、集合、数据、枚举、结构体都是值传递。
- 如果一定要把一个值传递的类型的数据变为引用传递模型的话,可使用关键字'inout'
func rectangle(inout width:Int, increased:Int = 1 ) {
width += increased
}
var value:Int = 10
rectangle(&value) // 结果是11
rectangle(&value,100) // 结果是111
-
函数返回值
func rectangleArea(width:Double, increased:Double = 1 ) -> (area:Double,height:Double) //返回面积和高度
-
函数类型
- 函数类型包括函数参数类型和返回值类型
(Double, Double) -> Double //传入宽高,计算面积
- 这个就是函数类型,函数类型可以作为其他函数的返回类型
- 比如写一个通用的方法来计算更多种图形的面积,这时可以使用这个函数类型作为返回值
- 函数类型还可以作为参数类型使用,可以直接使用返回值作为参数,然后可以在函数内部调用这个函数
-
函数重载
- 和C++中函数重载类似,但是在swift中
函数返回值类型 、外部参数名 也可以作为不同函数的判断标准
-
嵌套函数
泛型和泛型函数
-
泛型就是在运行时才确定类型的一种机制,这个C++中的泛型如出一辙
-
就是定义一个模板,使用多种场景
-
函数参数或者返回值到运行时才能确定
func add(a:Int, b:Int) -> Int
{
return a + b
}
func add(a:Double, b:Double) -> Double
{
return a + b
}
-
如果用泛型计算两个数的和,可以写成下面这个样
func add<T>)(a:T, b:T) -> T {
return a + b
}
// 或者指定多重类型
func add<T,U>(a:T, b:U) -> T {
return a + T(b)
}
-
如果比较两个类型的话,那么必须要遵守Comparable 协议才可以
func isEquals<T: Comparable>(a:T, b:T) -> Bool {
return (a == b)
}
闭包
使用举例
-
完整版本
{(a:Int, b:Int) -> Int in
return a + b
}
-
简化版本 {a,b in return a + b }
- 如果闭包中只有一条return语句,那么return 语句可以省略
{a,b in a + b }
- 缩写参数名称
{$0 + $1} swift会自动推到出参数类型,$0表示第一个参数,$1表示第二个参数
- 闭包作为返回值,直接可以为变量和常量赋值
let reslut:Int = {(a:Int, b:Int) -> Int in
return a + b
}(10, 89)
-
捕获上下文中的变量和常量
- 嵌套函数和闭包可以访问其所在上下文中的常量和变量,这就是
捕获值 。即便是定义这些常量或变量的作用域已经不存在,嵌套函数或闭包仍然可以在函数体内或闭包内修改或引用这些值。
swift中的面向对象
枚举
-
swift中枚举可以存储多种数据类型,并不是真正的整数
// 默认并不是整形
enum WeekDays {
case Monday
case Tuesday
case Wednesday
case Thursday
case Friday
}
// 简写
enum WeekDays {
case Monday, Tuesday, Wednesday, Thursday, Friday
}
-
注意:在switch中使用枚举类型时,语句中的case必须全部包含枚举中所有成员,不能多也不能少,包括default语句。
-
指定没枚举的原始值,可以是字符、字符串、整数、浮点数等
// 指定枚举的原始值
enum WeekDays: Int {
case Monday = 0
case Tuesday
case Wednesday
case Thursday
case Friday
}
-
原始值使用的话,要用到函数 toRaw() 和 fromRaw()
结构体
- swift中结构体和类非常类似,可以定义成员变量和方法
- 结构体不具备继承、运行时强制类型转换、析构函数、引用计数等
- 除了对象是引用传递,其他数据类型都是值传递,引用之间的比较可以使用 ‘=’ 和 ‘!=’
可选类型和可选链
-
“?” 和 "!"
-
可选绑定 : 如果赋值不为nil的话就执行if语句
if let result: Double? = divide(100,0) {
print("success")
}
else {
print("failure")
}
-
强制拆封 : 使用 ! 来强制拆封
let result: Double? = divide(100,0)
print(result!)
-
可选链
- 一些可选类型内部包含其他可选类型,然后产生层级关系。
访问限定
- 访问范围的界定主要有:模块和源文件
- 访问级别:public、internal、private
- 可修饰类、结构体、枚举等面向对象的类型,还可以修饰变量、常量、下标、元组、函数、属性等。以上这些统称“实体”
- 使用方式
-
public : 只要在import进所在模块,那么在该模块中都可访问
-
internal : 只能访问自己模块的任何internal实体,不能访问其他模块中的internal实体,默认就是internal修饰符
-
private : 只能在当前源文件中访问的实体。
- 设计原则
- 如果是自己在本文件内部使用,就用默认的就行。
- 如果是开发第三方框架的话,那么一定要设计好访问级别,接口一定要public。其他的可以private
属性和下标
1、存储属性
2、计算属性
-
计算属性本身不存储数据,只从其他存储属性中获得数据。类、结构体、枚举都可以定义计算属性
-
计算属性只能使用var 修饰
var firstName: String = "Jone"
var secondName: String = "Hu"
// 计算属性
var fullName: String {
get {
return firstName + "." + secondName
}
set (newValue) {
let names = newValue.componentsSeparatedByString(".")
firstName = names[0]
secondName = names[1]
}
}
-
只读计算属性,只写set方法即可,这是可以省略set ,直接return 即可
var firstName: String = "Jone"
var secondName: String = "Hu"
// 计算属性
var fullName: String {
return firstName + "." + secondName
}
3、静态属性
4、下标
-
一些集合类型,可以使用下标访问
/**
* 定义二维数组,使用下标访问数组
* 内部还是一个一维数组,不过展示给外界的时一个二维访问方式
*/
struct DoubleArray {
// 属性定义
let rows: Int
let cols: Int
var grid: [Int]
// 构造方法
init(rows: Int, cols: Int) {
self.rows = rows
self.cols = cols
grid = Array(count: rows * cols, repeatedValue: 0) // 利用泛型创建一个数组
}
// 下标定义
subscript(row: Int, col: Int) -> Int {
get {
return grid[row * col + col]
}
set (newValue) {
grid[row * col + col] = newValue
}
}
}
// 使用二维数组
var arr2 = DoubleArray(rows: 10, cols: 10)
// 初始化二维数组
for var i = 0; i < 10; i++ {
for var j = 0; j < 10; j++ {
arr2[i,j] = i * j
}
}
// 输出二维数组
for var i = 0; i < 10; i++ {
for var j = 0; j < 10; j++ {
print("\t \(arr2[i,j])")
}
print("\n")
}
方法
- 类、结构体、枚举中都可以定义方法
- 这里主要说结构体和枚举中方法的定义
- 默认情况下,结构体和枚举中的方法是不能修改属性的
- 如果要修改属性的话,需要在方法之前加关键字
mutating ,称之为变异方法
静态方法
-
结构体和枚举中静态方法用static ,类中静态方法使用class
-
1、结构体中的静态方法
/**
* 结构体中的静态方法
*/
struct Account {
var owner: String = "Jack"
static var interestRate: Double = 0.668
// 静态方法
static func interestRateBy(amount: Double) -> Double {
return interestRate * amount
}
func messageWith(amount: Double) -> String {
let interest = Account.interestRateBy(amount)
return "\(self.owner) 的利息是 \(interest)"
}
}
// 调用静态方法
print(Account.interestRateBy(10_000.00))
//
var myAccount = Account()
print(myAccount.messageWith(10_000))
-
2、枚举中的静态方法
/// 枚举中的静态方法
enum Account1 {
case 中国银行
case 中国工商银行
case 中国建设银行
case 中国农业因银行
static var interestRate: Double = 0.669
// 静态方法定义
static func interestBy(amount: Double) -> Double {
return interestRate * amount
}
}
// 静态方法的调用
print(Account1.interestBy(10_000.00))
-
3、类中的静态方法
/// 类中的静态方法,使用关键字class
class Account2 {
var ower: String = "Jack"
class func interestBy(amount: Double) -> Double {
return 0.889 * amount
}
}
// 调用静态方法
print(Account2.interestBy(10_000.00))
构造和析构
- 只有类和结构体才有构造
init() 和析构函数deinit
- 在创建实例过程中需要一些初始化操作,这个过程称为构造
- 在实例最后被释放的过程中,需要清楚资源,这个过程称为析构
- 注意: 构造器 可以重载,没有返回值
构造器
- 构造器主做一些属性的初始化操作
- 如果不写init方法,那么会自动生成一个空的init构造器
- 如果有继承关系,要先调用父类的构造器
- 横向代理与向上代理
- 横向代理:构造器调用发生在本类内部,添加
convenience 关键字即可作为便利构造器,便利构造器必须调用本类内部的其他构造器
- 向上代理:有继承关系,就先调用父类的构造器
析构器
- 析构器只作用于类
- 析构器没有返回值,没有参数,不能重载
继承
- swift单继承
- 重写属性、下标以及方法
- 重写父类的方法使用
override
- 终止属性或者方法的继承可以使用
final
- 类型检查
is as Any AnyObject
-
is 类型判断
-
as 类型转换
-
Any 任何类型,包括类和其他数据类型
-
AnyObject 任何类
扩展和协议
扩展extension
- 扩展的类型可以使类、结构体、枚举
- 扩展可以增加属性和方法
- 扩展计算属性、方法、构造器、下标
- 注意:扩展类的构造器的时只能增加遍历构造器,指定构造器和析构器只能由源类型指定
协议 protocol
- 类似C++中的纯虚类
- 可以定义属性和方法
- 协议可以继承协议
swift内存管理
- swift内存管理遵循ARC特性
- 对引用类型进行引用计数,基本数据类型由系统管理
循环引用问题
- swift中解决循环引用由两种方式
- 1、弱引用(
weak reference )
- 2、无主引用(
unowned reference )
- 弱引用可以没有值,因此必须设置成可选类型
- 无主引用适用于引用对象永远有值
闭包中的循环引用问题
-
闭包中的循环引用的解决方法和上面的一样,使用弱引用和无主引用
class Person {
let firstName: String = "Jack"
let secondName: String = "lu"
/**
* 解决闭包强循环引用
*/
lazy var fullName: (String, String) -> String = {
// [weak self] (firstName: String, secondName: String) -> String in
[unowned self] (firstName: String, secondName: String) -> String in
return firstName + secondName
}
}
OC与Swift
-
OC和swift可以混合开发
-
1、swift 调用 OC
- 桥接文件 "<工程名>-Bridging-Header.h"
- 在桥接文件中引入OC头文件即可
-
2、OC调用swift
- 包含头文件,这个头文件命名样式 "<工程名>-swift.h"
- 在swift源文件中要把类声明为
@objc
- 这时新建
swift 类就不需要选择新建swift文件,而是选择Cocoa Touch Class ,然后选择语言类型位swift
|
请发表评论