Swift3.0 语法总结

代码下载

代码下载地址

前言

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

数据类型

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

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

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

var x = 12
let y = 42.0

2.字符串的声明:

let name : String = "綦帅鹏"
let age : Int = 10
print("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指定为nil
var product = ["name":"iPhone5", "size":"4寸"]
print(product)
//取值
print(product["name"]!)
//添加数据
product["address"] = "香港"
print(product)
//修改数据
product["size"] = "4英寸"
print(product)
//删除数据
product["address"] = nil
print(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 = 75
var speed = 0
while 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 = 3
var num2 = 2
var num3 = 4
print(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.875
print(loanCalculator(amount: 10000, interestRate: &rate, years: 5, calculator: simpleClosure))

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

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

/// 颜色类型枚举
enum ColorType {
    case RGB
    case CMYK
    case HSB
}
let type: ColorType = .RGB
print(type)

/// 学科枚举
enum Subject: String {
    case Chinese = "语文"
    case Math = "数学"
    case English = "英语"
}
let subjece: Subject = .Chinese
print(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 = 2345346457
print(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.5
num.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 = bClass
bClass.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 = dClass
dClass.c = cClass
cClass = nil
dClass = 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 = 10
student.info()
student = nil
class 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 = 10
people.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 = 1
let b: Int = 1
class 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)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容