Swift3.0 语法总结

来源:互联网 发布:婴儿肥 知乎 编辑:程序博客网 时间:2024/06/06 09:21

代码下载

代码下载地址

前言

最近找工作,很多单位都需要掌握Swift这门语言,发现Swift将是大势所趋啊!自己之前也断断续续学习过一阵子,但是学以致用啊,项目开发都是用Objective-C不用就容易忘,这段时间得闲就整理出这篇文章,可以说是自己的学习回顾吧,希望对大家有用!这都是些基本的东西,没有做过多的描述。后面我会更新一些Swift较深入探讨的文章。

数据类型

1.基本数据类型有:整型:Int, 浮点型:Float, 双精度浮点型:Double, 字符型:Character, 字符串型:String

定义常量:var x: Float = 42.0
定义变量:let y: Int = 12

注意:Swift可以推断出数据的类型,所以在变量常量声明的时候可以省略数据类型。

var x = 12let y = 42.0

2.字符串的声明:

let name : String = "綦帅鹏"let age : Int = 10print("My name is " + name + "," + String(age) + " years old!")print("My name is \(name), \(age) years old!")

注意:
- Swift中字符串可以通过”+”来拼接。
- 在Swift字符串中可以通过”(名称)”来获取常量、变量的值。

3.元组:元组是一系列不同类型数据的有序集合,可以包含不同的数据类型,通过”.下标”来获取对应的数据。

//元组let student = ("綦帅鹏", 27, "打球")print("学生:\(student.0), \(student.1)岁,喜欢\(student.2)!")

4.数组:数组是一系列相同类型的数据的有序集合,数组中的数据类型必须相同。

//数组,数组中数据的类型必须相同var studentsName = ["张三", "李四", "王五"]//添加数据studentsName.append("赵六")print(studentsName)//添加多个数据,也可以理解为数组合并studentsName += ["綦帅鹏", "綦朝晖"]print(studentsName)//添加数据到指定位置studentsName.insert("廖腾逸", at: 0)print(studentsName)//修改数据studentsName[1] = "廖雨琦"print(studentsName)//移除数据studentsName.remove(at: 2)print(studentsName)//移除最后一个数据studentsName.removeLast()print(studentsName)print(studentsName)//移除所有数据studentsName.removeAll()print(studentsName)

5.字典:字典是一系列相同类型的数据的无序集合,数据是由键值对存在的,并且键不能为nil。

//字典:不能将key指定为nilvar product = ["name":"iPhone5", "size":"4寸"]print(product)//取值print(product["name"]!)//添加数据product["address"] = "香港"print(product)//修改数据product["size"] = "4英寸"print(product)//删除数据product["address"] = nilprint(product)//字典数组搭配print([[1, 2, 3], ["1", "2", "3"]])print([["name": "张三", "address": "湖南"], ["name": "李四", "address": "北京"]])//空数组var arr: Array<Int> = []arr.append(1)print(arr)var otherArr = [Int]()otherArr += [2]print(otherArr)//空字典var dic = Dictionary<String, String>()dic["name"] = "张三"print(dic)

6.数组与字典的遍历

//数组遍历for item in [1, 2, 3] {    print(item)}for (index, item) in [1, 2, 3].enumerated() {    print("\(index): \(item)")}//遍历字典for (key, value) in ["name": "张三", "address": "湖南"] {    print("\(key):\(value)")}

流程控制

1.for循环

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]for num in arr {    print(num)}for item in 1...10 {    print(item)}for item in 1..<10 {    print(item)}for item in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].reversed() {    print(item)}

2.if…else…选择

let lightColor = "red"if lightColor == "red"{    print("Stop!")}else{    print("Go!")}

3.while循环和switch…case…选择

let limit = 75var speed = 0while speed < 100 {    speed += 1    switch speed {    case 0..<20:        print("太慢啦!")    case 20..<40:        print("快点行吗!")    case 40..<60:        print("速度起来啦!")    case 60...limit:        print("别超速呀,我的哥!")    default:        print("超速啦,我的哥!")    }    if speed > limit {        break    }}

注意:在Swift中可以不需要使用break关键字

函数

1.函数的定义:func 函数名(参数1名: 参数类型, 参数2名: 参数类型) -> 返回值类型

func add(num: Int, otherNum: Int) -> Int {    return num + otherNum}print(add(num: 10, otherNum: 20))

2.参数个数变化的函数定义:在函数的最后一个参数中用…来添加多个参数

//可变参数,只能在函数的最后一个参数中用...来添加多个参数func addAllNums(nums: Float...) -> Float {    var result : Float = 0.0    for item in nums {        result += item;    }    return result}print(addAllNums(nums: 10, 20, 30, 40, 50, 60, 70, 80, 90, 100))

3.带默认参数的函数

//默认参数func circleArea(r: Double = 10) -> Double{    return M_PI*r*r}print(circleArea())print(circleArea(r: 100))

4.高阶函数:Swift中函数可以做参数也可以做返回值

//找出最大数func findMax(nums: Double...) -> Double {    var result : Double = -Double.infinity//负无穷大    for item in nums {        if item > result {            result = item        }    }    return result}print(findMax(nums: 12, 3333, 32413, 324, 34124, 3432))//找出最小数func findMin(nums: Double...) -> Double {    var result : Double = Double.infinity    for item in nums {        if item < result {            result = item        }    }    return result}print(findMin(nums: 12, 3333, 32413, 324, 34124, 3432))//函数返回函数func findNum(type: String) -> (Double...) -> (Double) {    if type == "max" || type == "Max" {        return findMax    }    return findMin}print(findNum(type: "Max")(1,2,3,4,32,32,4,34,23) + findNum(type: "Min")(2,32,323,233,1,323))

5.函数嵌套:在函数中定义使用函数

//函数嵌套func randomNum(type:String) -> Int {    func randomPositive() -> Int {        return Int(arc4random())    }    func randomNegative() -> Int {        return -(Int)(arc4random())    }    if type == "randomPositive" {        return randomPositive()    }    return randomNegative()}print(randomNum(type: "randomPositive"))print(randomNum(type: "randomNegative"))

注意:函数中的参数inout关键字会改变函数体外的变量值,同时在调用该函数的时候,此参数需传地址而不是值。

//变量参数,inout关键字会改变函数体外的变量值func ascendingSort(num1: inout Int, num2: inout Int, num3: inout Int) -> [Int]{    var temp : Int    if num1 > num2 {        temp = num1;        num1 = num2;        num2 = temp;    }    if num2 > num3 {        temp = num2;        num2 = num3;        num3 = temp;    }    return [num1, num2, num3]}var num1 = 3var num2 = 2var num3 = 4print(ascendingSort(num1: &num1, num2: &num2, num3: &num3))print([num1, num2, num3])

闭包

1.说明:闭包与函数类似,就是一个代码块分装了其所处环境的所有状态。在闭包之前声明的所有变量常量都会被闭包所捕获,从本质上说闭包保留定义它时的程序状态。函数是有名称的闭包,闭包是无名称的函数。
2.定义一个计算单利的闭包

var simpleClosure = {(amount: Double, interestRate: inout Double, years: Int) -> Double in    interestRate = interestRate/100    var interest = Double(years) * interestRate * amount    return interest + amount}

3.高阶函数就是使用(闭包或函数)作为参数或返回值

//闭包做函数的参数func loanCalculator(amount: Double, interestRate: inout Double, years: Int, calculator: (Double, inout Double, Int) -> Double) -> Double{    return calculator(amount, &interestRate, years)}var rate : Double = 3.875print(loanCalculator(amount: 10000, interestRate: &rate, years: 5, calculator: simpleClosure))

Swift中的类基本上就类的变量、常量、函数、继承等内容,十分简单方便。

枚举

枚举的定义方式如下,可以给枚举类型的数据设置值也可以不设置值

/// 颜色类型枚举enum ColorType {    case RGB    case CMYK    case HSB}let type: ColorType = .RGBprint(type)/// 学科枚举enum Subject: String {    case Chinese = "语文"    case Math = "数学"    case English = "英语"}let subjece: Subject = .Chineseprint(subjece)

结构体

Swift中的结构体和C语言类似,同时Swift的结构体还包括方法,这使得与类十分相似。不过结构体是不能继承的,并且结构体是值类型的数据结构,而类是引用类型的数据结构。
- 值类型:每次赋值都将创建副本,并把副本赋值给新的变量或常量,变量或常量存储的是副本。
- 引用类型:说白了,引用类型就是指针,不管赋值给多少变量或者常量,他们都指向同一个对象,变量和常量存储的都是指向这个对象的引用,而不是副本。

struct Color {    var R: Double = 0.0    var G: Double = 0.0    var B: Double = 0.0    var Alpha: Double = 0.0    func stringValue() -> String {        let limit: Double = 255.0        let rInt: Int = Int(self.R*limit)        let gInt: Int = Int(self.G*limit)        let bInt: Int = Int(self.B*limit)        let alphaInt: Int = Int(self.Alpha*limit)        let result: String = String.init(format: "%02X%02X%02X%02X", rInt, gInt, bInt, alphaInt)        return result    }}let red: Color = Color(R: 1.0, G: 0.0, B: 0.0, Alpha: 1)print(red)print(red.stringValue())

协议

指定了类和结构需要实现的方法和变量,optional关键字可以定义协议中选择实现的方法和变量,一个结构体或者类可以实现多个协议,值得注意的是协议之间是可以继承的。

//多协议protocol AreaComputetionProtocol {    func computeArea() -> Double}protocol PerimeterComputetionProtocol {    func computePerimeter() -> Double}struct RectAngle: AreaComputetionProtocol, PerimeterComputetionProtocol {    var width, height: Double    internal func computeArea() -> Double {        return width*height    }    internal func computePerimeter() -> Double {        return 2*(width + height)    }}let rect: RectAngle = RectAngle(width: 3.0, height: 4.0)print(rect.computeArea())print(rect.computePerimeter())//协议继承protocol TriangeleProtocol: AreaComputetionProtocol, PerimeterComputetionProtocol {    var a: Double {get set}    var b: Double {get set}    var c: Double {get set}    var base: Double {get set}    var height: Double {get set}}struct Triangle: TriangeleProtocol {    var a: Double = 0.0    var b: Double = 0.0    var c: Double = 0.0    var base: Double = 0.0    var height: Double = 0.0    func computeArea() -> Double {        return base*height/2.0    }    func computePerimeter() -> Double {        return a + b + c    }}let triangle: Triangle = Triangle(a: 3, b: 4, c: 5, base: 3, height: 4)print(triangle.computeArea())print(triangle.computePerimeter())

说到协议就不得不说委托,委托是为了让一个类或结构体能够将工作和决策交给另一个类或结构去完成。

//委托:让一个类或结构能够将工作和决策交给另一个类或结构去完成/// 售货机协议protocol VendingMathineProtocol {    /// 是否投币    var coinInserted: Bool {get set}    /// 能否售货    func shouldVend() -> Bool}/// 自动售货机类,遵守售货机协议class Vendor: VendingMathineProtocol {    var coinInserted: Bool = false    /// 如果投币则售货否则不售货    ///    /// - Returns: 是否售货    func shouldVend() -> Bool {        if coinInserted {            coinInserted = false            return true        }        else        {            return false        }    }}/// 可乐机类class ColaMethine {    // 自动售货机类,遵守售货机协议    var vendor: VendingMathineProtocol    init(vendor: VendingMathineProtocol) {        self.vendor = vendor    }    /// 投币    func insertCoin() {        vendor.coinInserted = true    }    /// 销售可乐按钮事件    func pressColaButton() -> String {        if vendor.shouldVend() {            return "Here's a cola!"        }        else        {            return "You must insert coin!"        }    }    /// 销售啤酒按钮事件    func pressRootBeerButton() -> String {        if vendor.shouldVend() {            return "Here's a Root Beer!"        }        else        {            return "You must insert coin!"        }    }}let methine: ColaMethine = ColaMethine.init(vendor: Vendor.init())print(methine.pressColaButton())methine.insertCoin()print(methine.pressColaButton())methine.insertCoin()print(methine.pressRootBeerButton())print(methine.pressColaButton())

扩展

不继承而扩展类的功能,扩展能够以非侵入式的方式,增加类、结构、甚至基本类型的行为和功能,类似于Objective_C的类别,但是强大得多。基本使用如下:

// MARK: - 可乐机的扩展extension ColaMethine {    /// 健怡可乐按钮事件    func pressDietColaButton() -> String {        if vendor.shouldVend() {            return "Here's a Diet Cola!"        }        else        {            return "You must insert coin!"        }    }}methine.insertCoin()print(methine.pressDietColaButton())

1.扩展基本数据类型:不能在扩展中添加常规存储属性,但可以添加计算属性:值是通过计算获得的属性

let limit: Double = 1024.0// MARK: - 为Int64扩展属性,获取存储单位的换算结果extension Int64 {    var K: String {return String.init(format: "%fK", Double(self)/limit)}    var M: String {return String.init(format: "%fM", Double(self)/limit/limit)}    var G: String {return String.init(format: "%fG", Double(self)/limit/limit/limit)}    var T: String {return String.init(format: "%fT", Double(self)/limit/limit/limit/limit)}}let bytes: Int64 = 2345346457print(bytes.K)print(bytes.M)print(bytes.G)print(bytes.T)

2.mutating关键字:如果要修改自身的值而不是返回计算的结果,那么就得使用mutating关键字

// MARK: - 为Double数据类型扩展方法extension Double {    /// 平方值    mutating func squra() {        self = self*self    }    /// 立方值    mutating func cube() {        self = self*self*self    }}var num: Double = 1.5num.squra()print(num)num.cube()print(num)

Swift内存管理

Swift以ARC方式为引用类型数据管理内存,这种方式是由编译器提供支持的。每一个引用类型的数据都有一个引用计数的的属性,当这个对象被创建的时候它的引用计数就为1,当这个对象在应用程序运行过程中被传递,就可能被多个“所有者”持有并使用。当“所有者”获得所有权时引用计算就相应加1,而在放弃所有权时引用计数就相应减1,直到引用计数为0时(所有的“所有者”都放弃了所有权),对象就会被销毁,它所占用的内存归还给内存池,供其他对象使用。

1.循环引用:循环引用就是指不同对象之间相互持有对方,这样造成了对象永远被“所有者”所占有,而无法释放,从而形成内存泄漏。
- 普通对象之间的循环引用:这种循环引用可以使用weak关键字来打破。

//循环引用class ClassA {    var b: ClassB!    //销毁时调用    deinit {        print("\(type(of: self)) 销毁了!")    }}class ClassB {    var a: ClassA!    //销毁时调用    deinit {        print("\(type(of: self)) 销毁了!")    }}var aClass: ClassA! = ClassA()var bClass: ClassB! = ClassB()aClass.b = bClassbClass.a = aClass//使用"weak"可以解决对象之间相互引用而造成的循环引用class ClassC {    var d: ClassD!    //销毁时调用    deinit {        print("\(type(of: self)) 销毁了!")    }}class ClassD {    weak var c: ClassC!    //销毁时调用    deinit {        print("\(type(of: self)) 销毁了!")    }}var cClass: ClassC! = ClassC()var dClass: ClassD! = ClassD()cClass.d = dClassdClass.c = cClasscClass = nildClass = nil
  • 闭包内的循环引用:闭包是引用类型的数据,类的实例变量强引用了闭包,而如果闭包中再引用了类对象的话,就会造成循环引用。在闭包定义中添加”[unowned self] in”可以解决闭包内的循环引用。
class Student {    var name: String = ""    var age: Int = 0    lazy var info: () -> Void = {        print("name:\(self.name), age:\(self.age)")    }    deinit {        print("\(type(of: self)) 销毁了!")    }}var student: Student! = Student()student.name = "张三"student.age = 10student.info()student = nilclass People {    var name: String = ""    var age: Int = 0    lazy var info: () -> Void = { [unowned self] in        print("name:\(self.name), age:\(self.age)")    }    deinit {        print("\(type(of: self)) 销毁了!")    }}var people: People! = People()people.name = "张三"people.age = 10people.info()people = nil

说明:一个对象在销毁的时候会调用deinit,而一个变量赋值为nil时就会放弃对原有对象的持有。

泛型

不指定数据的类型,只是指定一个占位符。编译器负责对数据类型进行检查。使用方式如下:

func valueEqual<T: Equatable>(value1: T, value2: T) -> Bool {    return value1 == value2}

运算符重载:只需定义一个运算符命名的函数就可以对运算符进行重载。

/// 二维矩阵结构体struct TwoDimensionalMatrix {    var a11: Double, a12: Double    var a21: Double, a22: Double}/// 重载+运算符,实现二维矩阵的相加func +(matrix: TwoDimensionalMatrix, otherMatrix: TwoDimensionalMatrix) -> TwoDimensionalMatrix {    return TwoDimensionalMatrix.init(a11: matrix.a11 + otherMatrix.a11, a12: matrix.a12 + otherMatrix.a12, a21: matrix.a21 + otherMatrix.a21, a22: matrix.a22 + otherMatrix.a22)}/// 重载*运算符,实现二维矩阵的相乘func *(matrix: TwoDimensionalMatrix, otherMatrix: TwoDimensionalMatrix) -> TwoDimensionalMatrix {    return TwoDimensionalMatrix.init(a11: matrix.a11 * otherMatrix.a11, a12: matrix.a12 * otherMatrix.a12, a21: matrix.a21 * otherMatrix.a21, a22: matrix.a22 * otherMatrix.a22)}let matrix: TwoDimensionalMatrix = TwoDimensionalMatrix.init(a11: 1, a12: 2, a21: 3, a22: 4)let otherMatrix: TwoDimensionalMatrix = TwoDimensionalMatrix.init(a11: 1, a12: 2, a21: 3, a22: 4)print(matrix + otherMatrix)print(matrix * otherMatrix)

相等与相同

相等是指值相等,相同是指指向的对象为同一个对象。使用==来判断值的相等,用===来判断是否为同一个对象。

let a: Int = 1let b: Int = 1class IntClass {    var value: Int = 0    init(value: Int) {        self.value = value    }}let intA: IntClass = IntClass.init(value: 1)let intB: IntClass = IntClass.init(value: 1)print(a == b)print(a != b)print(intA === intB)print(intA !== intB)
0 0