IOS学习笔记01-swift语言基础

166 阅读6分钟

IOS学习笔记01 - swift

swift基础

swift既可以面向对象,也可以面向过程。

环境

xcode -> file -> playground

  • 在playground里可以快速查看代码结果。
1.变量类型
  • let常量,var变量
  • 声明可以使用unicode字符(如各种奇怪字符)
  • 变量声明之后,值可以改变,类型不能改变
  • 类型可以使用别名,即新的名字
  • (变量名) 用来引用变量,如print("\(s) ")
2.元组

定义类似c++的元组turple,如(int,string),(int,int,string)

  • 定义元组
let http404Error = (404,"Not Found")
  • 分解元组并使用常量
  • 不需要分解的直接 _ 替代
let http404Error = (404,"Not Found")
let (statusCode, statusMessage) = http404Error
print("The status code is \(statusCode)")
// prints "The status code is 404"
print("The status message is \(statusMessage)")
// prints "The status message is Not Found"
  • 使用下标访问元组元素
print("The status code is \(http404Error.0)")
//prints "The status code is 404"
print("The status message is \(http404Error.1)")
// prints "The status message is Not Found" 
  • 直接命名元素
let http200Status = (statusCode: 200, description: "OK")
3.可选项

在swift里,下面的代码是不被允许的。

var str:String = "test"
str =nil

因此需要使用可选项

var str:String? = "test"
str = nil

swift设置可选项的原因是:避免代码使用错误或者丢失的数据,如一个返回字符串的函数,可能什么都不返回。通过可选项避免这种事情的发生,相当于有一个检查的功能。 可选项是个盒子:

  • 如果为nil,那么它就是个空盒子;
  • 如果不为nil,那么盒子里装的就是被包装类型的数据
  • 如果要从可选项中取出被包装的数据(将盒子里装的东西取出来),需要使用感叹号(!)进行强制解包;
  • 在取出的可选类型的变量后面加上!即可。
  • 空盒子不能强制解包
var age: Int? = 10;
var ageInt: Int = age!;
ageInt += 10;

可选项绑定
没看出有啥用?

4.可选链

可选项在解包时,可能会出现下面问题:

class Person {
    var residence: Residence?
}
class Residence {
    var numberOfRooms = 1
}
let john = Person()
//将导致运行时错误
let roomCount = john.residence!.numberOfRooms

如下报错:

Fatal error: Unexpectedly found nil while unwrapping an Optional value

上面的类里有一个可选项,创建一个空的实例,然后访问空实例的可选项,就会错误,因为此时变量值为空。

如下面这个例子,这份代码的意思是,取到赋值,取不到设置为unknown

let album = albumReleased(year: 2006) ?? "unknown"
print("The album is (album)")
4.错误处理

try/catch 机制,类似Java

func makeASandwich() throws {
    // ...
}
do {
    try makeASandwich()
    eatASandwich()
} catch Error.OutOfCleanDishes {
    washDishes()
} catch Error.MissingIngredients(let ingredients) {
    buyGroceries(ingredients)
}
5.断言
6. 枚举

简单例子

enum WeatherType {
    case sun, cloud, rain, wind, snow
}

func getHaterStatus(weather: WeatherType) -> String? {
    if weather == WeatherType.sun {
        return nil
    } else {
        return "Hate"
    }
}

getHaterStatus(weather: WeatherType.cloud)

也可以这样写

enum WeatherType {
    case sun
    case cloud
    case rain
    case wind
    case snow
}

func getHaterStatus(weather: WeatherType) -> String? {
    if weather == .sun {
        return nil
    } else {
        return "Hate"
    }
}
//或者这样
func getHaterStatus(weather: WeatherType) -> String? {
    switch weather {
    case .sun:
        return nil
    case .cloud, .wind:
        return "dislike"
    case .rain:
        return "hate"
    }

}

getHaterStatus(weather: .cloud)

有附加值的枚举

enum WeatherType {
    case sun
    case cloud
    case rain
    case wind(speed: Int)
    case snow
}

func getHaterStatus(weather: WeatherType) -> String? {
    switch weather {
    case .sun:
        return nil
    case .wind(let speed) where speed < 10:
        return "meh"
    case .cloud, .wind:
        return "dislike"
    case .rain, .snow:
        return "hate"
    }
}

getHaterStatus(weather: WeatherType.wind(speed: 5))

可选项貌似也是有附加值的枚举实现的?

7.特性/属性

swift可以方便在对象属性改变发生之前或者发生之后,添加代码逻辑 属性观察器: willset,属性改变之前 didset,属性改变之后

struct Person {
    var clothes: String {
        willSet {
            updateUI(msg: "I'm changing from (clothes) to (newValue)")
        }

        didSet {
            updateUI(msg: "I just changed from (oldValue) to (clothes)")
        }
    }
}

func updateUI(msg: String) {
    print(msg)
}

var taylor = Person(clothes: "T-shirts")
taylor.clothes = "short skirts"

在java里,一般会给属性写set和get方法。

在swift里,一般会这样写:

struct Person {
    var age: Int

    var ageInDogYears: Int {
        get {
            return age * 7
        }
    }
}

var fan = Person(age: 25)
print(fan.ageInDogYears)

get写法类似

8.控制流
Repeat-While

就是do-while

9.guard语句

guard语句的基本用法

guard <condition> else { return }

guard语句适用的情况

当条件不满足,后续代码无需执行的情况。 使用guard语句的方便之处在于,你可以清楚地看到程序把那些错误的情况判断掉;

例如一个用户登录的例子:

func log(account: String, pwd: String) {
    guard !account.isEmpty && !pwd.isEmpty else {
        return
    }
    // 登录逻辑
}

注意判断逻辑别写反!!!!!

guard 如果条件为真,才会执行后面的逻辑

写反的情况:

guard account.isEmpty && pwd.isEmpty else {
    return
}

swift集合

1. 数组

数组初始化

  • + 直接连接数组
  • +=添加一个或者多个
var someInts = [Int]()
var shoppingList: [String] = ["Eggs", "Milk"]

for-in 遍历数组

for item in shoppingList {
    print(item)
}

包含索引遍历

for (index, value) in shoppingList.enumerated() {
    print("Item \(index + 1): \(value)")
}
2.Set

初始化

var letters = Set<Character>()
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]

for-in 遍历

for genre in favoriteGenres.sorted() {
    print("\(genre)")
}
3.字典

初始化

var namesOfIntegers = [Int: String]()

其他类似c++

函数

基本用法

func greet(person: String, alreadyGreeted: Bool) -> String {
    if alreadyGreeted {
        return greetAgain(person: person)
    } else {
        return greet(person: person)
    }
}
print(greet(person: "Tim", alreadyGreeted: true))

多返回值

func minMax(array: [Int]) -> (min: Int, max: Int) {
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

面向对象

1.类和结构体区别

  • 类可以继承等
  • 结构体是值类型,类是引用类型
  • String,Array,Dictionary都是作为struct实现的

2.继承

  • 表示继承
  • Java里@override表示重写父类方法,swift里override关键字修饰重写的方法/属性
  • final 和Java中类似,可以用来修饰阻止重写的部分

3.类型转换

  • is关键字用于检查一个实例是否属于某个类
  • as?转换的是一个可选项,as!是强制转换,转换不成功会报错。 常见写法:
for item in sa {
    // 类型转换的条件形式
    if let show = item as? Chemistry {
        print("化学主题是: '(show.physics)', (show.equations)")
        // 强制形式
    } else if let example = item as? Maths {
        print("数学主题是: '(example.physics)',  (example.formulae)")
    }
}
  • Any和AnyObject

AnyObject表示的是任何类的实例 Any表示任何类型,包括变量类型,方法等

闭包

自我理解 : 闭包在swift里,相当于自包含的函数块,就一个方便的函数写法。

常用形式:

{(parameters) -> return type in
   statements
}

例如

let studname = { print("Swift 闭包实例。") }
studname()
let divide = {(val1: Int, val2: Int) -> Int in 
   return val1 / val2 
}
let result = divide(200, 20)
print (result)

闭包表达式

提供一些语法优化,使得闭包写法变简单 字典序排序写法(有点像c++的friend函数);

import Cocoa

let names = ["AT", "AE", "D", "S", "BE"]

// 使用普通函数(或内嵌函数)提供排序功能,闭包函数类型需为(String, String) -> Bool。
func backwards(s1: String, s2: String) -> Bool {
    return s1 > s2
}
var reversed = names.sorted(by: backwards)

print(reversed)

参数名称缩写

$0,$1,$2按顺序来简化闭包中的参数

import Cocoa

let names = ["AT", "AE", "D", "S", "BE"]

var reversed = names.sorted( by: { $0 > $1 } )
print(reversed)

也还可以这样写

var reversed = names.sorted( by: > )

尾随闭包

上面的排序算法可以这样写:把{}拉到()后面 :

let names = ["AT", "AE", "D", "S", "BE"]

//尾随闭包
var reversed = names.sorted() { $0 > $1 }
print(reversed)

捕获值

这个嵌套的函数forIncrement相当于一个外部名,内嵌函数使用的的是引用,不是复制值,所以所以参数可以一同改变

func makeIncrementor(forIncrement amount: Int) -> () -> Int {

    var runningTotal = 0

    func incrementor() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementor
}

let incrementByTen = makeIncrementor(forIncrement: 10)

// 返回的值为10

print(incrementByTen())

// 返回的值为20

print(incrementByTen())

// 返回的值为30

print(incrementByTen())

逃逸闭包

自动闭包

协议

协议规定了类型的属性和方法规范,set/get 指明可读可写

  • 协议可以继承
  • 协议可以合成

Mutating(变异)

在方法中改变实例时,可以用 Mutating修饰

构造器 协议可以要求遵循者显示实现构造器

和继承类的区别?

和实现接口的区别?

拓展

拓展就是向已有的类里添加新的属性、方法、构造器、下标,但不能重写。

  • 协议也可以扩展

访问控制

可以给类型修饰,也可以给对象、协议修饰 swift的模块:可以简单理解成程序

  • public 最宽权限
  • internal 自己能访问模块中的源文件,但别人不行
  • fileprivate 只能当前源文件里使用
  • private 只能类内或者结构体内访问