Swift快速入门指南

5,785 阅读13分钟

一、常量&变量

在Swift中规定:在定义一个标识符时必须明确说明该标识符是一个常量还是变量

1、使用 let 定义常量,定义之后不可以修改
let number = 10
// 常量不可以修改
number = 20 ❌
2、使用 var 定义变量,定义之后可以修改
var number = 10

number = 20 

⚠️编译器会根据给变量或常量所赋的值,推断它的数据类型。所以这里系统会认为number是Int类型的

⚠️ swift中输出语句:print函数

print("Hello Swift")

二、数据类型

Swift中的数据类型也有:整型/浮点型/字符串/对象类型/结构体类型等等

⚠️ Swift是强类型语言

// 定义变量时没有指定明确的类型,但是因为赋值给i一个20.20为整型.因此i为整型
var i = 20
// 如果之后赋值给i一个浮点型数值,则会报错
// i = 30.5 ❌

如果定义一个标识符时有直接进行赋值,那么标识符后面的类型可以省略

如果想要指定常量或变量的数据类型

var number:Float = 10
var name:String = "花花"

Swift中的基本运算

⚠️ Swift中在进行基本运算时必须保证类型一致,否则会出错

⚠️ 值不会隐式转换,需要显示转换成其他数据类型

let a = 10
let b = 3.14

// 错误写法
// let c = a + b ❌
// let c = a * b ❌

// 正确写法
let c = Double(a) + b
let d = a + Int(b)

三、字符串

字符串的使用

1、遍历字符串
// 字符串遍历
var str = "Hello, Swift"
for c in str {
    print(c)
}
2、字符串拼接
let str1 = "Hello"
let str2 = "Swift"
let str3 = str1 + str2
3、字符串插值
let age = 18
let result = "My name is Huahua, age is \(age)"
4、字符串的格式化
let str = String(format: "%@=%@", key, value)
5、使用2对3引号可以表示多行字符串
let string = """
Hello Swift!
Hello Swift!
Hello Swift!
"""

⚠️引号所在行,引号后不能有其他元素

四、数组

数组是一串有序的由相同类型元素构成的集合,数组中的集合元素是有序的,可以重复出现

1、数组的初始化

⚠️ 声明数组

// let代表不可变数组
let array:Array<String>

// var代表可变数组
var array: [String]

⚠️ 初始化数组

// 定义一个可变数组,必须初始化才能使用
var array1 : [String] = [String]()

// 定义一个不可变数组
let array2 : [Any] = ["花花", 18]

// 定义时直接初始化
var array = ["a", "b", "c"]

// 先定义,后初始化
var array : Array<String>
array = ["a", "b", "c"]
2、对数组的基本操作
// 添加数据
array.append("abc")

// 删除元素
array.removeFirst()

// 修改元素
array[0] = "asd"

// 取值
array[1]

// 数组合并
// 注意:只有相同类型的数组才能合并
var array1 = ["a", "b","c"]
var array2 = ["d", "e"]
var array3 = array1 + array2
3、数组的遍历
// 遍历数组
for i in 0..<array.count {
    print(array[i])
}

// forin方式
for item in array {
    print(item)
}

// 设置遍历的区间
for item in array[0..<2] {
    print(item)
}

五、字典

字典是由两部分集合构成的,一个是键(key)集合,一个是值(value)集合。键集合是不能有重复元素的,值集合可以重复,键和值是成对出现的。

1、字典的初始化
// 定义一个可变字典
var dict1 : [String : Any] = [String : Any]()

// 定义一个不可变字典
let dict2 = ["name" : "花花", "age" : 18]

⚠️ 声明字典

var dict1: Dictionary<Int, String>
var dict2: [Int: String]
2、字典的基本操作
// 添加数据
dict["height"] = 1.88

// 删除字段
dict.removeValueForKey("height")

// 修改字典
dict["name"] = "花花"

// 查询字典
dict["name"]

// 字典的合并
var dict1 = ["name" : "花花", "age" : 18]
var dict2 = ["height" : 1.8]

// 字典不可以直接相加合并
for (key, value) in dict2 {
    dict1[key] = value
}
3、字典的遍历
// 遍历字典中所有的值
for value in dict.values {
    print(value)
}

// 遍历字典中所有的键
for key in dict.keys {
    print(key)
}

// 遍历所有的键值对
for (key, value) in dict {
    print(key)
    print(value)
}

六、元祖

元祖是一种数据结构,类似于数组或字典,用于定义一组数据

1、定义元祖
("1001", "花花", 18, 90)
(id:"1001", name:"张三", age:18, score:90)
2、元祖的简单使用
// 元祖:HTTP错误
// 写法一:
let error = (404, "Not Found")
print(error.0)
print(error.1)

// 写法二:
let error = (errorCode : 404, errorInfo : "Not Found")
print(error.errorCode)
print(error.errorInfo)

// 写法三:
let (errorCode, errorIno) = (404, "Not Found")
print(errorCode)
print(errorIno)

七、可选类型(Optional)

在swift开发中,nil也是一个特殊的类型。

1、可选类型的定义
// 写法一:定义可选类型
let string : Optional<String> = nil

// 写法二:定义可选类型,语法糖(常用)
let string : String? = nil

// 错误写法
// let string : String = nil ❌
2、可选类型的使用
// 定义可选类型
var string : String? = nil

// 给可选类型赋值
string = "Hello world"

// 打印结果
print(string)

// 结果:Optional("Hello world")
// 因为打印出来的是可选类型,所有会带Optional
3、解包

解包就是取出可选类型的真实值

print(string!) // 结果:Hello world

⚠️注意:如果可选类型为nil,强制取出其中的值(解包),程序会崩溃

string = nil
print(string!) // 报错 

// 正确写法:
if string != nil {
    print(string!)
}

// 简单写法:为了让在if语句中可以方便使用string
if var str = string {
    print(str)
}
4、可选类型使用实例
// 通过该方法创建的URL,可能有值,也可能没有值

// 正确写法:使用可选类型来接收
let url : URL? = URL(string: "http://www.baidu.com")

// 错误写法:如果返回值是nil时,就不能接收了
let url : URL = URL(string: "http://www.baidu.com")

// 通过url来创建request对象
if let tempUrl = url {
    let request = NSURLRequest(URL: tempUrl)
}

八、函数

函数格式:

func 函数名(参数列表) -> 返回值类型 {
    代码块
    return 返回值
}
  • func是关键字,多个参数列表之间可以用逗号(,)分隔,也可以没有参数
  • 使用箭头“->”指向返回值类型
  • 如果函数没有返回值,返回值为Void.“-> 返回值类型”部分可以省略
1、常见函数类型

<1 没有参数,没有返回值

func test() -> Void {
    print("Hello Swift")
}

// 调用函数
test()

// 简单写法
// 如果没有返回值,后面的内容可以都不写
func test2() {
   print("Hello Swift")
}

<2 有参数,没返回值

func test(name : String) {
    print("Hello\(name)")
}
test(name: "Swift")

<3 没参数,有返回值

func getSth() -> String {
    return "花花"
}
var str = getSth()
print(str)

<4 有参数,有返回值

func sum(num1 : Int, num2 : Int) -> Int {
    return num1 + num2
}
var result = sum(20, num2: 30)
print(result)
2、外部参数&内部参数

在函数外面可以看到的参数,就是外部参数。在函数内部可以看到的参数,就是内部参数。

⚠️ 如果不想要外部参数,可以在参数名称前加_

// number1、number2和number3是外部参数的名称

func mutiple(number1 num1 : Int, number2 num2 : Int, number3 num3 : Int) -> Int {
    return num1 * num2 * num3
}
var result1 = mutiple(number1: 20, number2: 4, number3: 5)
3、默认参数

某些情况,如果没有传入具体的参数,可以使用默认参数

func makecoffee(type :String = "卡布奇诺") -> String {
    return "制作一杯\(type)咖啡。"
}

let coffee1 = makecoffee("拿铁")
let coffee2 = makecoffee()
4、可变参数

swift中函数的参数个数可以变化,它可以接受不确定数量的输入类型参数(必须具有相同的类型),我们可以通过在参数类型名后面加入(...)的方式来指示这是可变参数

func sum(numbers:Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total
}

sum(100.0, 20, 50)
5、引用类型

默认情况下,函数的参数是值传递.如果想改变外面的变量,则需要传递变量的地址

inout关键字

func swap(a : inout Int, b : inout Int) {
   let temp = a
   a = b
   b = temp
}

var a = 10
var b = 20
swap(a: &a, b: &b)
print("a:\(a), b:\(b)")
6、方法重载

方法重载:方法名称相同,但是参数不同

func mutiple(_ num1: Int, _ num2 :Int) -> Int {
    return num1 * num2
}

var result2 = mutiple(20, 20)

九、 闭包

闭包是一个特殊函数

1、定义闭包

类型:(形参列表)->(返回值)

技巧:定义闭包类型时,直接写()->().再填充参数和返回值

{
    (形参) -> 返回值类型 in
    // 执行代码
}
2、闭包的使用
// 定义网络请求类
class HttpTool: NSObject {
    func loadRequest(callBack: ()->()){
        print("加载数据..")
        callBack()
    }
}

// 网络请求
let httpTool = HttpTool()
httpTool.loadRequest ({ () -> () in
    print("加载完成")
})   
3、闭包的简写
  • 如果闭包没有参数,没有返回值.in和in之前的内容可以省略
httpTool.loadRequest({
    print("加载完成")
})

⚠️ 尾随闭包

  • 尾随闭包写法
    • 如果闭包是函数的最后一个参数,则可以将闭包写在()后面
    • 如果函数只有一个参数,并且这个参数是闭包,那么()可以不写
httpTool.loadRequest() {
    print("加载完成")
}
// 开发中建议该写法
httpTool.loadRequest {
    print("加载完成")
}
4、闭包的循环使用
  • 如果在HttpTool中有对闭包进行强引用,则会形成循环引用
class HttpTool: NSObject {
    // 定义属性,强引用传入的闭包
    var callBack : (()->())?

    func loadRequest(callBack : ()->()){
        callBack()
        self.callBack = callBack
    }
}
  • swift中解决循环引用的方式
// [weak self] () -> () in
httpTool.loadRequest { [weak self] in
    self.view.backgroundColor = UIColor.redColor()
}

十、 懒加载

定义:用到时候才加载

懒加载的本质是,在第一次使用的时候执行闭包,将闭包的返回值赋值给属性

  • lazy的作用是只会赋值一次
lazy var array : [String] = {
    () -> [String] in
    return ["a", "b", "c"]
}()

十一、类

Swift是一门面向对象开发的语言,面向对象的基础是类

1、类的定义
class 类名 : SuperClass {
    // 定义属性和方法
}

⚠️ 定义的类,可以没有父类.那么该类是 rootClass

2、类的属性
  • Swift中类的属性有多种
    • 存储属性:存储实例的常量和变量
    • 计算属性:通过某种方式计算出来的属性
    • 类属性:与整个类自身相关的属性

存储属性

  • 存储属性是最简单的属性,它作为类实例的一部分,用于存储常量和变量
  • 可以给存储属性提供一个默认值,也可以在初始化方法中对其进行初始化
class Student : NSObject {
    // 存储属性
    var age : Int = 0
    var name : String?
    var englishScore : Double = 0.0
    var mathScore : Double = 0.0
}

// 创建学生对象
let stu = Student()
// 给存储属性赋值
stu.age = 10
stu.name = "花花"
stu.englishScore = 80.0
stu.mathScore = 90.0

计算属性

  • 计算属性并不存储实际的值,而是提供一个getter和一个可选的setter来间接获取和设置其它属性
  • 存储属性一般只提供getter方法
  • 如果只提供getter,而不提供setter,则该计算属性为只读属性,并且可以省略get{}
class Student : NSObject {
    // 存储属性
    var age : Int = 0
    var name : String?
    var englishScore : Double = 0.0
    var mathScore : Double = 0.0
    
    // 计算属性
    var averageScore : Double {
        get {
            return (englishScore + mathScore) / 2
        }
        // newValue是系统分配的变量名,内部存储着新值
        set {
            self.averageScore = newValue
        }
    }
}

类属性

  • 类属性是与类相关联的,而不是与类的实例相关联
  • 类属性使用static来修饰
class Student : NSObject {
    // 存储属性
    var age : Int = 0
    var name : String?

    var englishScore : Double = 0.0
    var mathScore : Double = 0.0

    // 计算属性
    var averageScore : Double {
        get {
            return (englishScore + mathScore) / 2
        }

        // 没有意义.newValue是系统分配的变量名,内部存储着新值
        set {
            self.averageScore = newValue
        }
    }

    // 类属性
    static var corseCount : Int = 0
}

// 设置类属性的值
Student.corseCount = 3
3、监听属性的改变

Swift中可以通过属性观察者来监听和响应属性值的变化

  • 通常是监听存储属性和类属性的改变.(对于计算属性,我们不需要定义属性观察者,因为我们可以在计算属性的setter中直接观察并响应这种值的变化)

  • 我们通过设置以下观察方法来定义观察者

    • willSet:在属性值被存储之前设置。此时新属性值作为一个常量参数被传入。该参数名默认为newValue,我们可以自己定义该参数名
    • didSet:在新属性值被存储后立即调用。与willSet相同,此时传入的是属性的旧值,默认参数名为oldValue
class Person : NSObject {
    var name : String? {
        // 可以给newValue自定义名称
        willSet (){ 
            // 属性即将改变,还未改变时会调用的方法
            // 在该方法中有一个默认的系统属性newValue,用于存储新值
            print(newValue)
        }
        didSet (oldValue) {
            // 属性值已经改变了,会调用的方法
            // 在该方法中有一个默认的系统属性oldValue,用于存储旧值
            print(oldValue)
        }
    }
    var age : Int = 0
    var height : Double = 0.0
}

let p : Person = Person()

// 在赋值时,监听该属性的改变
// 在OC中是通过重写set方法
// 在swift中,可以给属性添加监听器
p.name = "花花"

十二、类的构造函数

  • 创建一个类时,必然会调用一个构造函数
  • 即便是没有编写任何构造函数,编译器也会提供一个默认的构造函数。
  • 如果是继承自NSObject,可以对父类的构造函数进行重写
1、构造函数的基本使用
class Person: NSObject {
    var name : String = ""
    var age : Int = 0

    // 重写了NSObject(父类)的构造方法
    override init() {
        name = ""
        age = 0
    }
}

// 创建一个Person对象
let p = Person()
2、初始化时给属性赋值

很多时候,我们在创建一个对象时就会给属性赋值,可以自定义构造函数 ⚠️ 如果自定义了构造函数,会覆盖init()方法.即不在有默认的构造函数

class Person: NSObject {
    var name : String?
    var age : Int = 0

    // 自定义构造函数,会覆盖init()函数
    init(name : String, age : Int) {
        self.name = name
        self.age = age
    }
}

// 创建一个Person对象
let p = Person(name: "花花", age: 18)

十三、Swift逻辑分支

通过分支语句可以控制程序的执行流程

  • 在Swift的判断句中必须有明确的真假 false/true
1、if语句
let a = 10

// 错误写法:❌
//if a {
//    print("a")
//}

// 正确写法
if a > 9 {
    print(a)
}

这个是可选类型,因为只有声明成可选类型后,才可以判断是否为空

let view : UIView? = UIView()

// 判断如果view有值,则设置背景颜色
// 错误写法 ❌
//if view {
//    view.backgroundColor = UIColor.redColor()
//}

if view != nil {
    view!.backgroundColor = UIColor.redColor()
}
2、if/else if/else 语句
let score = 87

if score < 60 {
    print("不及格")
} else if score <= 70 {
    print("及格")
} else if score <= 80 {
    print("良好")
} else if score <= 90 {
    print("优秀")
} else {
    print("完美")
}
3、三目运算符
var a = 10
var b = 50

var result = a > b ? a : b
print(result)
4、guard语句

guard是Swift2.0新增的语法,它设计的目的是提高程序的可读性

  • guard语法:
    • 当条件表达式为true时候跳过else语句中的内容,执行后面的代码
    • 条件表达式为false时候执行else语句中的内容,跳转语句一般是return、break、continue和throw
guard 条件表达式 else {
    // do sth..
    return
}
do sth...

使用实例:

var age = 18

func online(age : Int) -> Void {
    guard age >= 18 else {
        print("回家去")
        return
    }

    print("可以上网")
}

online(age)
5、switch分支

switch后可以不跟(),case后可以不跟break(默认会有break)

let sex = 0

switch sex {
case 0 :
    print("男")
case 1 :
    print("女")
default :
    print("其他")
}

如果希望出现之前的case穿透,则可以使用关键字fallthrough

let sex = 0

switch sex {
case 0:
    fallthrough
case 1:
    print("正常人")
default:
    print("其他")
}

swift支持多种数据类型

  • 浮点型的switch判断
let f = 3.14
switch f {
case 3.14:
    print("π")
default:
    print("not π")
}
  • 字符串类型
let opration = "+"

switch opration {
    case "+":
        print("+")
    case "-":
        print("-")
    case "*":
        print("*")
    case "/":
        print("/")
default:
    break
}
  • switch支持区间判断
let score = 88

switch score {
case 0..<60:
    print("不及格")
case 60..<80:
    print("及格")
case 80..<90:
    print("良好")
case 90..<100:
    print("优秀")
default:
    print("满分")
}

十四、循环

1、for循环
for i in 0..<10 {
    print(i)
}

for i in 0...10 {
    print(i)
}
2、while循环
var a = 0
while a < 10 {
    a++
}
3、repeat while 循环
let b = 0
repeat {
    print(b)
    b++
} while b < 20