Swift 学习笔记
iOS开发学习中的简单记录
文章目录
Swift基本语法
注释
//
/*
多行注释
*/
let
初始化后无法修改
var
初始化后可修改
let name1//常量
var name2//变量
运算符
运算符+
、-
、*
、/
、%
、+=
、-=
、*=
、/=
逻辑运算符 Bool
、&&
、||
、!
数据类型 Int
、Double
、Bool
、String
、String()
、\()
判断运算符 ==
、!=
用于判断运算符两边的指针是否相同 ===
、!==
let num = 1
let num2 : Int = 1 //说明数据类型
let day = "5"
let output = "星期" + day
**字符串插值 String Interpolation **
省略+
var day = "5"
let output = "星期" + day + ",快放假了!"
let newOutput = "星期\(day),快放假了" //省略
函数
定义及使用
定义函数时使用:
指定类型
调用函数时使用:
指定参数值
func sayHi(){
print("Hi")
}
func sayHi(name: String){
print("Hi\(name)")
}
sayHi(name: "Liu")
参数标签、默认值、返回值
参数标签,函数传值默认为参数名,有参数标签就通过参数标签传值,_
代表省略标签,直接传入值。
//不要参数标签
func sayHi_1(_ name : String){
print("Hi \(name)")
}
sayHi_1("Liu")
//默认值
func sayHi_2(n name : String, age : Int = 0){
print("Hi \(name) \(age)")
}
sayHi_2(n: "Liu",age: 2)
//返回值
func sayHi_3(n name : String, age : Int = 0) -> String{
"Hi \(name) \(age)" // return "Hi \(name) \(age)"仅包含一个可返回的值可省略
}
print(sayHi_3(n: "Liu"))
函数重载 Function Overload
根据传参的不同调用同名但功能不同的函数
func driveForward() {
print("move.....")
}
func driveForward(meters: Int) {
print("move.....\(meters)")
}
driveForward() //move.....
driveForward(meters: 10) //move.....10
函数返回值
指定函数返回值数据类型 func() -> 返回值数据类型{}
仅包含一个可以返回的数值,可省略return
func sayHi_3(n name : String, age : Int = 0) -> String{
"Hi \(name) \(age)" // return "Hi \(name) \(age)"
}
print(sayHi_3(n: "Liu"))
函数的格式
数组
定义数组
var weightArray_1 : [Int] = [] //至少定义为空
var weightArray_1 : [Int] = [61,70,55]
let weightArray_2 = [61,70,55]
添加修改
weightArray_1[0] = 65 //[65,70,55]
weightArray_1.append(45) //[65,70,55,45]
weightArray_1 += [11,22] //[65,70,55,45,11,22]
weightArray_1.insert(33, at:4) //[65,70,55,45,33,11,22]
weightArray_1.remove(at: 1) //70 移除并返回值
数组函数
weightArray_1.firstIndex(of: 55) //查询值的序列号
weightArray_1.isEmpty //false
weightArray_1.count
weightArray_1.contains(55)
weightArray_1.min()
weightArray_1.sort()
weightArray_1.shuffle()
weightRecords.removeSubrange(3...7)
生产数组
.map
对数组中所有的数值依次进行指定的运算生产新数组
.filter
对数组中所有的数值依次进行筛选生产新数字
let goal = 50
let result = weightArray_1.map { $0 - goal } //所有数值-50
let result = weightArray_1.filter { $0 > goal } //大于50
let menu = [["apple"],["milk"]]
数组遍历
for car in cars {
}
字典
括号中多个:
代表定义字典
student : [String: Int] = [:]
student = ["Tom" : 20, "Bob" : 18]
student["Tom"] = nil //删除
字典与数组混用
let dailyMenu = [
"早餐":["面包","牛奶"],
"午餐":["面","饭"]
]
循环
for _ in 1...5 {
print("Hello")
}
repeat {
} while Condition
闭包
func compare(first: Int, second: Int) ->Bool {
return first < second
}
//闭包完整写法
let closure = { (first: Int, second: Int) -> Bool in
return first < second
}
//闭包使用
var number = [2, 18, 0, -9, 30]
number.sort(by: closure)
//双击throws自动出现
number.sort(by: { (first: Int, second: Int) -> Bool in
return first < second
})
几种精简写法
//尾部闭包法 Trailing Code
//省略函数括号直接使用{}
number.sort { (first: Int, second: Int) -> Bool in
return first < second
}
//省略数据类型,和返回类型,因sort函数已规定好闭包的形式
number.sort { (first, second) in
return first < second
}
//省略括号和return
number.sort { first, second in first < second }
//短参数
number.sort { $0 < $1 }
可选项参数 Optional
考虑到用户的注册途径不同,可能使用第三方入口登陆,系统中可能存,或没存这个用户的用户名
var username: String? = "小王"
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mh4SySnJ-1660480762153)(https://cdn.jsdelivr.net/gh/Unitary-orz/unitary_oss/img/2022/08/20220814203637.png)]
强行读取 Force Unwrap
假设变量一定存在,并将结果转化为相应的数据类型,无法将nil
读取
print(username!)
判断后读取
先判断是否为nil
,再读取
if username != nil{
let checkUsername = username!
print(checkUsername)
}
if let checkUsername = username {
print(checkUsername) //局部变量
}
guard let checkUsername = usernaem {
print(checkUsername)
}
guard let
突破局部变量,必须有返回值或其他终止
func guarDemo(){
guard let safeUsername = username else {
print("is nil")
return
}
print(safeUsername)
}
本质是一个枚举型
var policyNote: String?
policyNote = nil
policyNote = Optional.none
结构
struct Player {
var name: String
let initHealth = 100
}
mutating
若方法函数需要更改属性的数值,则需要在方法的关键词 func 前加上另一个关键词可变更
struct Player {
mutating func damaged(by health: Int) {
}
}
lazy
懒,忽略掉初始化,初始化过后再执行代码
调用此变量的函数都需要加上
mutating
let maxHealth = 100
lazy var currentHealth = maxHealth
属性观察器 Property Observer
willSet
指的是检测到该属性将要发生变化,新的值以 newValue
表示
didSet
属性变化后运行,被改变的值以oldValue
var livesRemaining = 5 {
willSet {
print("警告:还剩下\(newValue)条命")
}
didSet {
if liveRemaining != 0 {
print("已满血复活")
}
else {
print("游戏结束")
}
}
}
预计算属性 Computed Property
get
负责读取预计算属性的值, 只包含 get 中的内容时,关键词get
可以省略set
则代表赋值
var isPalerOutOfLives: Bool{
get {
liveRemaining == 0 ? true : false
}//判断生命是否为0,并返回到newValue
set {
if newValue {
liveRemaining = 0
}
}
}
初始化器 Initializers
默认初始化未设置值的属性
init(name: String){
self.name = name
}
init(name: String, currentHealth: Int, liveNumber: Int){
self.name = name
self.currentHealth = currentHealth
self.liveNumber = liveNumber
}
类型属性 Type Property
静态属性,以Type
名为前缀调用,Type.xxxx``Type.xxx()
static var count = 0
init(name: String){
self.name = name
Player.count += 1
}
static func palyerNumber(){
print("现在的玩家数量为\(count)")
}
var playerLiu = Player(name: "Liu")
var playerWang = Player(name: "Wang")
Player.palyerNumber() //2
不是静态的为实体属性 Instance Property
,
枚举 Enumeration
enum EnergySource {
case electricity
case diesel
case gasoline
}
var selectEnergy = EnergySource.electricity
和switch配套
var selectEnergy = EnergySource.electricity
var policyNote: String?
switch selectEnergy {
case .electricity:
policyNote = "电动车"
case .diesel:
policyNote = "柴油车"
case .gasoline:
policyNote = "汽油车"
}
print(policyNote ?? "暂无说明")
类
class 必须写明初始化器,而 struct 自带默认的初始化器。
class Car {
var brand: String
init(brand: String) {
self.brand = brand
}
}
继承
子类: 父类
继承父类override
重载父类super.init()
调用父类
class Seden: Car {
override init(brand: String, year: Int, energy:EnergySource) {
super.init(brand: brand, year: year, energy: energy)
assistantEquipped = false
}
func upgrade() {
}
}
子类数组,储存在数组子类自动升级为父类
var teslaModel3 = Seden(brand: "Tesla", year: 2017, energy: .electricity)
var toyotaHilux = Track(brand: "Toyota", year: 1968, energy: .gasoline )
let cars = [teslaModel3, toyotaHilux] //子类变成父类类型
is
判断类型
as?
判断并改变类型
if car is Seden {
print("一辆轿车")
}
//转回为子类类型,调用Seden的方法,升级配置
for car in cars {
if let teslaModel3 = car as? Seden {
teslaModel3.upgrade()
}
}
扩展 Extension
extension
对类型进行扩展扩展支持以下四种类型: 结构 struct、类 class 、枚举 enum以及 protocol
extension Car {
var quickInfo: String {
//省略了get
"The cat brand is \(brand), first built on \(year)"
}
}
print(teslaModel3.quickInfo)
类和结构
适用于反复使用的框架一般定义为class
不适合反复使用的实体和不需要继承常被定义为 struct
Apple 官方文档的建议是当需要创建一个新的自定义类别时,可以先将其定义为 struct
。只有你需要用到 class
继承的特性,或者是作为引用类型的特性时,再将其关键词换为 class
。
typealia 类型别名
typealias PhoneBook = [String: Int]
let phoneBook: PhoneBook = ["王": 123456]
协议 Protocol
类似Java中的接口
protocol Expressible {
var name: String { get }
init(name: String)
}
属性:
- 需统一使用关键词
var
{ get }
实体只读{ get set }
可以被实体读取或更改
方法:不写具体方法,只定义
结构 struct、类 class 和枚举 enum可使用protocol
//结构可省略初始化
struct User {
var name: String
}
可等性 Equatable
自定义类型的等于判断所需要的protocol
Static Method static func == (Self, Self) -> Bool
struct Todo : Equatable {
var content: String
static func ==(lhs: Todo, rhs:Todo) -> Book {
return lhs.content == rhs.content
}
}
let todoOne = Todo(content:"Play game")
let todoTwo = Todo(content:"Write Artcle")
if (todoOne == todoTwo) {
print("Woo~")
}
只涉及基本类型可省略
struct Todo : Equatable {
var content: String
}
可比性 Comparable
自定义类型的大小判断所需要的protocol
static func < (lhs: Self, rhs: Self) -> Bool
struct Date {
let year: Int
let month: Int
let day: Int
}
extension Date: Comparable {
static func < (lhs: Date, rhs: Date) -> Bool {
if lhs.year != rhs.year {
return lhs.year < rhs.year //返回year Int 的比较结果
}
else if lhs.month != rhs.month {
return lhs.month < rhs.month
}
else {
return lhs.day < rhs.day
}
}
}
let date1 = Date(year: 1999, month: 07, day: 23)
let date2 = Date(year: 2000, month: 11, day: 29)
if date1 < date2 {
print("date1 older")
}
else {
print("data2 older")
}
可哈希性 Hashable
产生一个随机、不可重复、独特的值,可以满足字典的Key属性,即把同一个类的不同对象当作一个唯一的hash值
struct Name: Hashable {}
// 生成两个对象放入字典,无Hash性会报错,会把同一个类的对象当作同一个字典key
let todos [dayOne: todoOne, datTwo: todoTwo]
可辨识性 Identifiable
自定义一个标示值,需要添加一个id
值,SwiftUI 会根据这个独特的 id 来判断视图的复用
struct Name: Equatable, Identifiable, Codable{
var id = UUID()
可编码性
当代码需要被转化成可以永久存储的信息时,需经过Encode
let todoOne = Todo(content:"test")
/* 可被编码为数据
{
"content": "玩游戏",
"id": "274Dxxxxxx"
*/
异常处理
fatalErrot()
抛出严重的错误
throws
函数定义时,返回类型之前加上关键词
do-try-catch
覆盖的代码段,会出现报错的代码,捕捉异常
//枚举创建一种错误
enum PasswordError: Error {
case notLongEnoungh
}
func validPasswrod(_ password: String) throws -> Bool {
if password.count < 6 {
throw PasswordError.notLongEnoungh
}
return true
}
try?
后面接上可能抛出异常的函数,为可选类型(异常为nil
,正常函数返回值)
if let result = try? validPasswrod(passwd) {
print("valid \(result)")
} else {
print("invalid")
}
try!
若异常则中断程序,等同于fatalError()
CPU
GCD 的全称是 Grand Central Dispatch,中央调度系统,其任务便是将代码自动在恰当的时机分配给 CPU 中的不同核心来处理,我们所写的所有代码都会被 GCD 运行在「主队列 main」中。其使用方法是 DispatchQueue.main.async {}
并发运行 Concurrent,它指的是在你的明确指示下,让复杂任务到别的窗口运行,不要卡在主队伍中,默认提供的并发队列叫做全局队列 Globa
Quality of Service,简称** QOS** 负责告知全局队列中任务优先级的参数
.userInteractive
UI.userInitiated
用户发起的任务.utility
杂项.background
后台
DispatchQueue.gobal(qos: .backgroud).async {
}