Swift5.0笔记

文章目录

  • 参考
  • 基础部分
    • 1. 常量和变量
    • 2. 显式指定变量或常量类型
    • 3. 注释
    • 4. print输出
    • 5. 数据类型
    • 6. 元组Tuples
    • 7. 可选类型Optionals
    • 8. 错误处理
  • 运算符
    • 1. 三元运算符 `condition?exp1:exp2`
    • 2. Nil Coalesecing Operator
    • 3. 区间运算符
  • 字符串和字符
  • 集合
    • 1. 数组Arrays
    • 2. 集合Sets
    • 3. 字典
  • 控制流
    • 1. for循环中不需要取每一项的值
    • 2. repeat-while
    • 3. switch fallthrough
    • 4.guard
  • 函数
    • 1. 定义函数与调用
    • 2. 函数当做一种类型
  • 闭包
    • 1. 闭包表达式
    • 2. 其他
  • 枚举
    • 1.定义
    • 2.使用
    • 3.可遍历
    • 4. 带值
  • 类与结构体
    • 1. 不同点:
    • 2. 创建
    • 3. 创建实例
    • 4. 属性访问和修改`.`
    • 5. lazy关键字
    • 6. 计算属性
    • 7. 属性观察器`willSet` `didSet`
    • 8. 类属性
    • 9. 方法
    • 10. 类方法(static)
    • 11. 下标语法
  • 继承
  • 构造过程
    • 1. 构造方法为`init`
    • 2. 重写父类构造器
    • 3. convenience init
    • 4. 可失败构造器
    • 5. 必要构造器
  • 析构过程
  • 可选链式调用
    • 1. 定义
    • 2. 使用可选链式调用代替强制展开
  • 错误处理
    • 1. 方法抛出错误,称为throwing方法
    • 2. 不处理错误
    • 3. 处理一部分错误
    • 4. 处理所有错误
    • 5. 错误转换为可选值
    • 6. 禁用错误传递
    • 7. 指定清理操作
  • 类型转换
    • 1. 判断实例属于哪个特定的子类型`is`
    • 2. 将实例向下转换为特定的子类型`as?` `as!`
    • 3. `Any` 和 `AnyObject`
  • 嵌套类型
  • 扩展
  • 协议
    • 1. 创建
    • 2. 使用
    • 3. 属性要求
    • 4. 方法要求
    • 5. 构造器要求
    • 6. 协议的继承
    • 7. 组合协议
    • 8. 可选的协议要求`@objc`
    • 9. 提供默认实现
    • 10. `some`
  • 泛型
  • 访问控制
  • 常用类、协议、结构体
    • 1. Hashable
    • 2. Codable

参考

官方文档
菜鸟教程

基础部分

1. 常量和变量

– 常量声明let i = 0
– 变量声明var i = 0

2. 显式指定变量或常量类型

var msg:String
var msg:String = "msg"

3. 注释

– 单行 //...
– 多行/*......*/

4. print输出

print("\(表达式)")

5. 数据类型

– 浮点数Double 64位
– 浮点数Float 32位
– 整数类型Int,Int8,Int16,UInt8,UInt16
– 布尔类型Bool

6. 元组Tuples

– 声明
let t = (1,"a")
– 访问
t.1 t.2

7. 可选类型Optionals

– 含义:表示有值或没有值nil

//创建
var str1 : String?//str1为nil
var str2 : String? = "msg"//str2为msg
str2 = nil //str2为nil
//强制取值
print(/(str2!))
//可选绑定
if let number = Int(possibleNumer){
	//number是真实值,不为nil
}else{
	//number为nil
}

8. 错误处理

do{
	try ..
}catch Error{
	...
}catch Error2{
	...
}

运算符

1. 三元运算符 condition?exp1:exp2

2. Nil Coalesecing Operator

a??b等价于a != nil ? a! : b

3. 区间运算符

  • 闭区间a...b
for index in 1...5{
	//todo
}
  • 半开区间a..
for index in 0..<arr.count{
	//todo
}
  • 单侧区间
//索引2到结尾
for name in names[2...]{
	//todo
}
//索引0到2
for name in names[...2]{
	//todo
}

字符串和字符

  1. 多行用三个双引号"""..."""
  2. 字符串连接使用+
  3. 创建字符let c : Character = "!"
  4. 字符添加到字符串s.append(c)
  5. 字符串插值\(表达式)
  6. 字符串长度s.count
  7. 字符串索引s.startIndex s.index(before:s.endIndex) s.index(after:s.startInex) s.index(s.startIndex,offsetBy:7) s.indices
  8. 在指定位置插入字符或字符串s.insert(_:,at:) s.insert(contentsOf:at:)
  9. 子字符串s[..
  10. 比较字符串== !=
  11. 前后缀相等hasPrefix() hasSuffix()

集合

可变性(引用和内容):可变var ,不可变let

1. 数组Arrays

  • 创建
//空的
var arr = [Int]()
//带指定值
var arr = [1,3,5]
//
  • 数组拼接+
  • 数组属性
arr.isEmpty
arr.count
  • 数组操作
//访问
arr[0]
//追加
arr.append()
//插入
arr.insert(123,at:0)
//删除
arr.remove(at:0)
  • 遍历
//只元素
for item in arr{
	//todo
}
//元素和索引
for (index,value) in arr.enumerate(){
	//todo
}

2. 集合Sets

  • 创建
//空的
var s = Set<Character>()
//带值
var s : Set = ["a","b","c"] 

其他与Array类似

3. 字典

  • 创建
//空的
var dict = [Int:String]()
//带值
var dict = [1:"one",2:"two"]
  • 操作
//取值,返回optional
dict[1]
//添加或更新
dict[1] = "one"
if let oldValue = dict.updateValue("value",forKey:1){
	//key存在则更新并返回旧值,不存在则返回nil
}
//删除键值对
dict[1] = nil
dict.removeValue(forKey:1)
  • 遍历
for (k,v) in dict{}
for k in dict.keys{}
for v in dict.values{}

控制流

1. for循环中不需要取每一项的值

for _ in 1...5{
	//todo
}

2. repeat-while

即do while

3. switch fallthrough

switch中的case中隐式的加入了break,不需要break可以显式的加上fallthrough,case可以有多个值

switch value{
	case value1:
		...
	case value2,value3:
		...
	default:
		...
}

4.guard

//可以作为检验参数时使用
func f(person:[String,String]){
	guard let name = person["name"] else {
        return
    }
}

函数

1. 定义函数与调用

  • 一般
func f(para1:String)->String{
	return ""
}
  • 带有默认值
func f(para1:String="hello")->String{
	return ""
}
  • 无返回值
func f(para1:String){
}
  • 多返回值,返回元组
func f(para1:String) -> (a:Int,b:Int){
	return (a,b)
}
  • 返回Optional
func f() -> String?{
	//可以返回nil
}
  • 可以省略return
func f() -> String{
	"hello"
}
  • 可变参数
func f(para1:Int...) -> Int{
}
  • 输入输出参数(即按地址传递)
func f(para1:inout Int){
}

2. 函数当做一种类型

//当定义的函数为
func f(a:Int,b:Int)->Int{}
//函数f的类型为(Int,Int)->Int
//可以使用这种类型赋予变量
var v:(Int,Int)->Int = f
//或自动推断
var v = f

//函数类型可以作为参数
func f(AnotherF:(Int,Int)->Int){}
//函数类型可以作为返回值
func f() -> (Int)->Int{}
//可以在函数中定义函数
func f(){
	func f1(){}
	func f2(){}
}

闭包

简化函数类型作为参数传递

1. 闭包表达式

//sorted为例
//使用函数传递
func f(s1:String,s2:String)->Bool{s1>s2}
names.sorted(by:f)
//使用闭包表达式
names.sorted(by:{(s1:String,s2:String)->Bool in return s1>s2})
//进一步省略
names.sorted(by:{s1,s2 in s1>s2})
//参数名称缩写
names.sorted(by:{$0>$1})
//运算符方法
names.sorted(by:>)
//尾随闭包
names.sorted(){$0>$1}
  //当只有一个参数时,括号也可以省略
  names.sorted{$0>$1}

2. 其他

逃逸闭包
自动闭包

枚举

1.定义

enum CompassPoint {
    case north
    case south
    case east
    case west
}

2.使用

val s = CompassPoint.north

3.可遍历

enum CompassPoint : CaseIterable{
    case north
    case south
    case east
    case west
}
//获取所有case:
CompassPoint.allCases

4. 带值

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}
var productBarcode = Barcode.upc(8, 85909, 51226, 3)

类与结构体

1. 不同点:

  • 类实例没有默认的逐一构造器,结构体实例会有一个自动生成的逐一构造器
  • 类是引用类型,结构体是值类型

2. 创建

struct SPeople{
	var age:Int
	var name:String
}
class CPeople{}

3. 创建实例

var sp = SPeople()
var cp = CPeople()

4. 属性访问和修改.

p.name = ""

5. lazy关键字

//被lazy修饰的属性,在第一次被访问到的时候才被创建
class C{
	lazy var ...
}

6. 计算属性

获取该属性时,需要通过其他属性进行计算得到,设置改属性值时,其他属性的值可以发生变化

//例子:圆
struct Circle{
	var r:Double = 0.0
	var area:Double{
		get{
			return Double.pi*r*r
		}
		set(newArea){
			r = sqrt(newArea/Double.pi)
		}
	}
}
//上面get可以省略return
//set可以使用默认的newValue参数,简化为
set{
	r = sqrt(newValue/Double.pi)
}
//上面的计算属性area可以设置为只读,取消set
var area:Double{ Double.pi*r*r }

7. 属性观察器willSet didSet

//默认参数newValue,oldValue
class C{
	var v:Int=0{
		willSet{
            print("willSet:\(newValue)")
        }
        didSet{
            print("didSet:\(oldValue)")
        }
	}
}

8. 类属性

(类似java中的static)

struct/class S{
	static var v = ""
}
//static 换成 class可以允许子类重写
class C{
	class var v = ""
}

9. 方法

  • self关键字代表本实例
  • 在struct的方法中修改属性需要加mutating
struct S{
	var v = 0.0
	mutating func f(){
		v += 1
	}
}

10. 类方法(static)

class C{
	static func f(){}
	class func f(){}//允许子类重写
}

11. 下标语法

相当于用下标的方式调用函数

struct S{
	subscript(index:Int)->Int{
		get{}
		set{}
	}
}
//如果是只读
subscript(index:Int)->Int{
	return...
}
//调用
var s = S()
s[0]//get
s[0]=1//set

下标可以有多个参数,多种类型

subscript(a:Int,b:String)->Int{
	get{}
	set{}
}
  • 类下标
    static subscript

继承

基本与Java类似

  1. 声明继承class ChildClass : SuperClass
  2. 重写属性,方法等,在前面加上override
  3. 子类访问父类super.
  4. 防止继承或重写父类中加final

构造过程

与Java类似

1. 构造方法为init

class A{
	var i : Int = 0
	init(i:Int){
		self.i = i
	}
}

2. 重写父类构造器

override init(){
	super.init()
	...
}

3. convenience init

用于初始化时没有指定属性值,默认初始化属性

class Food {
    var name: String
    init(name: String) {
        self.name = name
    }

    convenience init() {
        self.init(name: "[Unnamed]")
    }
}
//调用
let f = Food()
//f.name为[Unnamed]

4. 可失败构造器

传入不符合条件的构造参数时,初始化失败
init?

5. 必要构造器

该类的子类都必须实现该构造器

class C{
	required init(){
		//...
	}
}
class D : C{
	required init(){
		//...
	}
}

析构过程

在实例被释放前需要执行的代码,每个类只能有一个析构器,析构器不能主动调用

deinit{
	//...
}

可选链式调用

1. 定义

  • 可选链式调用是一种可以在当前值可能为 nil 的可选值上请求和调用属性、方法及下标的方法。如果可选值有值,那么调用就会成功;如果可选值是 nil,那么调用将返回 nil。多个调用可以连接在一起形成一个调用链,如果其中任何一个节点为 nil,整个调用链都会失败,即返回 nil

2. 使用可选链式调用代替强制展开

//如果使用!强制展开可选值可能会引发错误
//代替方案为 :使用?
if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}

错误处理

1. 方法抛出错误,称为throwing方法

func f() throws -> String{
	//...
	throw Error..
}

2. 不处理错误

func f1() throws -> String{
	//...
	throw Error..
}
func f2() throws -> String{
	//...
	try f1()
}

3. 处理一部分错误

func f2() throws -> String{
	//...
	do{
		try f1()
	}catch is XXXError{
		//...
	}
}

4. 处理所有错误

func f2() -> String{
	//...
	do{
		try f1()
	}catch XXXError{
		//...
	}catch XXXXError{
		//...
	}catch{
		//...
	}
}

5. 错误转换为可选值

//出错时x为nil
let x = try? f1()

6. 禁用错误传递

//强制执行,不抛出
try!f1()

7. 指定清理操作

//退出代码块`{}`后执行的操作(延迟执行)
func open(filename) {
        let file = open(filename)
        defer {
            close(file)
        }
        while let line = try file.readline() {
            // 处理文件。
        }
        // close(file) 会在这里被调用,即作用域的最后。
    }

类型转换

1. 判断实例属于哪个特定的子类型is

item is Movie

2. 将实例向下转换为特定的子类型as? as!

item as? Movie //返回一个可选的Movie,转换失败则为nil
item as! Movie //强制转换为Movie类型

3. AnyAnyObject

//Any 可以表示任何类型,包括函数类型
//AnyObject 可以表示任何类类型的实例

嵌套类型

内部类

扩展

为已经存在的类,结构体,枚举,协议添加新功能
新功能包括:

添加计算型实例属性和计算型类属性
定义实例方法和类方法
提供新的构造器
定义下标
定义和使用新的嵌套类型
使已经存在的类型遵循(conform)一个协议
//添加方法
extension Double{
	var km:Double{
		self*1000.0
	}
}
//使用
var a = 1.2.km
//a的值为1200

协议

类似Java interface

1. 创建

protocol P{

}

2. 使用

//父类名在协议前
class C : SuperClass,FirstProtocal,AnotherProtocal{}

3. 属性要求

协议中指定属性名,类型,可读写

protocol P{
	var a : Int{get set}
	var b : Int{get}
	//类属性
	static c : Int{get set}
}

4. 方法要求

protocol P{
	func f() -> String
	static func f() -> Int
}

5. 构造器要求

protocol P{
	init(para:Int)
}
//required不可少
class C : P{
	required init(para:Int){
		
	}
}
//如果同时继承
class C : Super,P{
	required override init(para:Int){

	}
}

6. 协议的继承

protocol P : AnatherP{}
//如果继承AnyObject,那么该协议只能被类实现,不能被结构体实现
protocol P : AnyObject{}

7. 组合协议

//同时实现两个协议的类做为参数
func f(para:P1&P2){
}

8. 可选的协议要求@objc

9. 提供默认实现

通过extension

extension P{

}

10. some

  • 反向泛型,隐藏具体的返回类型
//不使用some
struct ContentView : View{
    var body : Text{
        Text("hello")
    }
}
//使用some
struct ContentView : View{
    var body: some View{
        Text("hello")
    }
}
//这里的用some可以指定返回实现了View的类即可,避免在方法声明时就写上具体类型,方便更新维护

泛型

  • 基本
func f<T>(a:T,b:T) -> T{}
//泛型约束
T约束为子类或实现协议
func f<T : SuperClass,P>
  • 在protocol中使用泛型associatedtype
protocol P{
	associatedtype T
	
}

访问控制

public
internal默认的,模块内
file_private
private

常用类、协议、结构体

1. Hashable

//标明一个类型是可哈希化的,这样这个类型可以在Set,Dictionary中使用,因为需要这个类型的hashValue。hash后可以使用==操作符。
struct Person:Hashable{
    var name:String
    var id:Int
    func hash(into hasher: inout Hasher) {
    	//需要用哪些属性进行hash计算,就combine进去,如果没有属性被combine进去,那么每个实例的hash值都是相同的
        hasher.combine(name) 
        hasher.combine(id)
        print("hash")
    }
}

2. Codable

//类似于java的序列化,可以将实例编码为外部数据,也可以用外部数据解码生成实例
//例JSONEncoder ,JSONDecoder
let s = S(name: "a", id: 1)
let str = String(data: try! JSONEncoder().encode(s), encoding:.utf8)!
//str 为 {"name":"a","id":1}
let jsonStr = """
{"name":"a","id":1}
"""
let s2 = try JSONDecoder().decode(S.self, from:jsonStr.data(using: .utf8)!)
//s2为S(name: "a", id: 1)

你可能感兴趣的:(swift)