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 只能类内或者结构体内访问