【Swift】100 Days of SwiftUI笔记(1-15)

笔记

本篇文章记录一下100 Days of SwiftUI第15天的笔记内容,因为第15天是对Swift 简介的总结,所以包含了前14天的笔记内容,具备Swift基础的同学可以跳过这部分笔记

创建常量和变量

// Swift可以创建常量和变量,但是常量通常更合适
// 变量
var name = "Ted"
name = "Rebecca"
// 常量
let user = "Daphne"
// 打印
print(user)

字符串

let actor = "Tom Cruise"
let actor = "Tom Cruise ??♂?"
// 特殊符号转转义前面加 \
let quote = "He tapped a sign saying \"Believe\" and walked away."
// 跨越多行的字符串
let movie = """
A day in
the life of an
Apple engineer
"""
// 获取字符数量.count
print(actor.count)
// 字符串是否以特定字母开头或结尾
print(quote.hasPrefix("He"))
print(quote.hasSuffix("Away.")) // Swift 中的字符串区分大小写,因此这里返回 false

整数

// Int
let score = 10
let higherScore = score + 10
let halvedScore = score / 2
// 支持复合赋值运算符
var counter = 10
counter += 5
// 是否能被某个数整除
let number = 120
print(number.isMultiple(of: 3))
// 特定范围内生成随机数
let id = Int.random(in: 1...1000)

浮点数

// Double
let score = 3.0

布尔类型

let goodDogs = true
let gameOver = false
// 反转值
var isSaved = false
isSaved.toggle()

拼接字符串

let name = "Taylor"
let age = 26
let message = "I'm \(name) and I'm \(age) years old."
print(message)

数组

var colors = ["Red", "Green", "Blue"]
let numbers = [4, 8, 15, 16]
var readings = [0.1, 0.5, 0.8]

print(colors[0])
print(readings[2])
// 添加元素
colors.append("Tartan")
// 删除指定元素
colors.remove(at: 0)
print(colors.count)
// 是否包含某个元素
print(colors.contains("Octarine"))

字典

let employee = [
    "name": "Taylor",
    "job": "Singer"
]

// 访问的元素不存在则会使用default的值
print(employee["name", default: "Unknown"])
print(employee["job", default: "Unknown"])

集合

// 集合与数组类似,但是是无序的,且忽略重复值
var numbers = Set([1, 1, 3, 5, 7])
print(numbers)
// 添加元素
numbers.insert(10)

枚举

enum Weekday {
    case monday, tuesday, wednesday, thursday, friday
}

var day = Weekday.monday
day = .friday

类型注释

let player: String = "Roy"
var luckyNumber: Int = 13
let pi: Double = 3.141
var isEnabled: Bool = true
var albums: Array<String> = ["Red", "Fearless"]
var user: Dictionary<String, String> = ["id": "@twostraws"]
var books: Set<String> = Set(["The Bluest Eye", "Foundation"])
// 数组和字典常用写法
var albums: [String] = ["Red", "Fearless"]
var user: [String: String] = ["id": "@twostraws"]
// 创建空的字符串数据
var teams: [String] = [String]()
var clues = [String]()
// 枚举
enum UIStyle {
    case light, dark, system
}

var style: UIStyle = .light

if判断语句

let age = 16

if age < 12 {
    print("You can't vote")
} else if age < 18 {
    print("You can vote soon.")
} else {
    print("You can vote now.")
}
// && 组合条件是两个部分都为真时,整个条件才为真,|| 则是其中任意一个条件为真,整个条件就为真
let temp = 26

if temp > 20 && temp < 30 {
    print("It's a nice day.")
}

Switch开关语句

enum Weather {
    case sun, rain, wind
}

let forecast = Weather.sun

switch forecast {
case .sun:
    print("A nice day.")
case .rain:
    print("Pack an umbrella.")
default:
    print("Should be okay.")
}

三元运算符

let age = 18
let canVote = age >= 18 ? "Yes" : "No"

循环

for循环

let platforms = ["iOS", "macOS", "tvOS", "watchOS"]

for os in platforms {
    print("Swift works on \(os).")
}
// 1...12是1到12,包含12
for i in 1...12 {
    print("5 x \(i) is \(5 * i)")
}
// 1..<13是1到12,不包含13
for i in 1..<13 {
    print("5 x \(i) is \(5 * i)")
}
// 不需要循环变量可以使用_
var lyric = "Haters gonna"

for _ in 1...5 {
    lyric += " hate"
}

print(lyric)

while循环

var count = 10

while count > 0 {
    print("\(count)…")
    count -= 1
}

print("Go!")
// continue跳过当前的循环迭代并继续执行以下循环
// break退出循环并跳过所有剩余迭代
let files = ["me.jpg", "work.txt", "sophie.jpg"]

for file in files {
    if file.hasSuffix(".jpg") == false {
        continue
    }

    print("Found picture: \(file)")
}

函数


    for i in 1...12 {
        print("\(i) x \(number) is \(i * number)")
    }
}

printTimesTables(number: 5)
// 返回值
func rollDice() -> Int {
    return Int.random(in: 1...6)
}

let result = rollDice()
print(result)
// 如果函数仅包含一行代码可以省略return
func rollDice() -> Int {
    Int.random(in: 1...6)
}

函数返回多个值

func getUser() -> (firstName: String, lastName: String) {
    (firstName: "Taylor", lastName: "Swift")
}

let user = getUser()
print("Name: \(user.firstName) \(user.lastName)")

// 如果不需要元祖中的所有值,可以解构元组,jiang将其分解为单独的值,_可以会儿一些值
let (firstName, _) = getUser()
print("Name: \(firstName)")

自定义参数标签

// 如果调用函数时不想传递参数名可以在参数名前面加_
func isUppercase(_ string: String) -> Bool {
    string == string.uppercased()
}

let string = "HELLO, WORLD"
let result = isUppercase(string)
// 设置函数外部、内部参数,for为外部参数,number为内部参数
func printTimesTables(for number: Int) {
    for i in 1...12 {
        print("\(i) x \(number) is \(i * number)")
    }
}

printTimesTables(for: 5)

提供参数的默认值

func greet(_ person: String, formal: Bool = false) {
    if formal {
        print("Welcome, \(person)!")
    } else {
        print("Hi, \(person)!")
    }
}

greet("Tim", formal: true)
greet("Taylor")

处理函数中的错误

// 定义可能发生的错误
enum PasswordError: Error {
    case short, obvious
}
// 编写可以抛出错误的函数
func checkPassword(_ password: String) throws -> String {
    if password.count < 5 {
        throw PasswordError.short
    }

    if password == "12345" {
        throw PasswordError.obvious
    }

    if password.count < 10 {
        return "OK"
    } else {
        return "Good"
    }
}
let string = "12345"

// 通过do包含抛出异常函数,用try调用抛出异常函数,然后捕获发生的错误
// 捕获错误时,需要有一个catch可以处理各种错误
do {
    let result = try checkPassword(string)
    print("Rating: \(result)")
} catch PasswordError.obvious {
    print("I have the same combination on my luggage!")
} catch {
    print("There was an error.")
}

闭包

// 可以将功能直接分配给常量或变量
let sayHello = {
    print("Hi there!")
}

sayHello()
// 接受参数,用in来标记参数和返回类型的结束,in后面是闭包本身的主体
let sayHello = { (name: String) -> String in
    "Hi \(name)!"
}
let team = ["Gloria", "Suzanne", "Tiffany", "Tasha"]

let onlyT = team.filter({ (name: String) -> Bool in
    return name.hasPrefix("T")
})
// 闭包在Swift中的使用,例如filter()方法通过测试运行数组的所有元素,测试为true的元素都会在新数组中返回
let team = ["Gloria", "Suzanne", "Tiffany", "Tasha"]

let onlyT = team.filter({ (name: String) -> Bool in
    return name.hasPrefix("T")
})

print(onlyT) // ["Tiffany", "Tasha"]
// 对上述闭包进行改造,因为闭包主体只有一行代码,可以删除return
let onlyT = team.filter({ (name: String) -> Bool in
    name.hasPrefix("T")
})

// 忽略闭包中的指定类型
let onlyT = team.filter({ name in
    name.hasPrefix("T")
})

// 改造为尾随闭包的特殊语法
let onlyT = team.filter { name in
    name.hasPrefix("T")
}

// Swift提供简短的参数名称,可以使用的$0
let onlyT = team.filter {
    $0.hasPrefix("T")
}

结构体

// 结构体可以创建自定义数据类型,并且具有自己的属性和方法
struct Album {
    let title: String
    let artist: String
    var isReleased = true

    func printSummary() {
        print("\(title) by \(artist)")
    }
}
// 使用初始化器创建结构体实例
let red = Album(title: "Red", artist: "Taylor Swift")
print(red.title)
red.printSummary()
// 结构体方法更改其属性时需要标记为mutating
mutating func removeFromSale() {
    isReleased = false
}

计算属性

struct Employee {
    let name: String
    var vacationAllocated = 14
    var vacationTaken = 0
    // 计算属性在每次访问时都会计算其值
    var vacationRemaining: Int {
        vacationAllocated - vacationTaken
    }
}

// 计算属性提供了getter和setter方法
var vacationRemaining: Int {
    get {
        vacationAllocated - vacationTaken
    }

    set {
        vacationAllocated = vacationTaken + newValue
    }
}

属性观察器

// 属性观察器是在属性更改时运行的代码片段
// didSet在属性刚刚更改时运行,willSet在属性更改之前运行
struct Game {
    var score = 0 {
        didSet {
            print("Score is now \(score)")
        }
    }
}

var game = Game()
game.score += 10
game.score -= 3

自定义初始化器

struct Player {
    let name: String
    let number: Int

    init(name: String) {
        self.name = name
        number = Int.random(in: 1...99)
    }
}

访问控制

// Swift 有多种用于结构内部访问控制的选项,但最常见的是四种:
// private:不要让结构体之外的任何东西使用它
// private(set):结构之外的任何内容都可以读取此内容,但不要让他们更改它
// fileprivate:不要让当前文件之外的任何内容使用它
// public:让任何人、任何地方都可以使用它
struct BankAccount {
    private(set) var funds = 0

    mutating func deposit(amount: Int) {
        funds += amount
    }

    mutating func withdraw(amount: Int) -> Bool {
        if funds > amount {
            funds -= amount
            return true
        } else {
            return false
        }
    }
}

let account = BankAccount(funds: 100)
print(account. funds) // ?
account.funds += 100 // ?

静态属性和方法

struct AppData {
    static let version = "1.3 beta 2"
    static let settings = "settings.json"
}

print(AppData.version)

// 类与结构体的区别一:可以通过继承其他类创建类
class Employee {
    let hours: Int

    init(hours: Int) {
        self.hours = hours
    }

    func printSummary() {
        print("I work \(hours) hours a day.")
    }
}

class Developer: Employee {
    func work() {
        print("I'm coding for \(hours) hours.")
    }
}

let novall = Developer(hours: 8)
novall.work()
novall.printSummary()

// 如果子类想更改从父类获得的方法,必须使用override
override func printSummary() {
    print("I spend \(hours) hours a day searching Stack Overflow.")
}
// 类与结构体的区别二:初始化器不同
// 1.Swift 不会为类生成成员初始化器。(类的初始化比结构体复杂得多)
// 2.如果子类具有自定义初始值设定项,则它必须始终在完成设置自己的属性后调用父类的初始值设定项。
// 3.如果子类没有任何初始值设定项,它将自动继承其父类的初始值设定项。
class Vehicle {
    let isElectric: Bool

    init(isElectric: Bool) {
        self.isElectric = isElectric
    }
}

class Car: Vehicle {
    let isConvertible: Bool

    init(isElectric: Bool, isConvertible: Bool) {
        self.isConvertible = isConvertible
        // 即上述的第二点
        super.init(isElectric: isElectric)
    }
}
// 类与结构体的区别三:类实例的所有副本共享其数据(类型引用),而结构体不是(值引用)
class Singer {
    var name = "Adele"
}

var singer1 = Singer()
var singer2 = singer1
singer2.name = "Justin"
print(singer1.name) // Justin,如果是Struct则是Adele
print(singer2.name) // Justin,如果是Struct则是Justin
// 类与结构体的区别四:类可以有一个析构器,当对对象的最后一个引用被销毁时,该析构器被调用
class User {
    let id: Int

    init(id: Int) {
        self.id = id
        print("User \(id): I'm alive!")
    }

    deinit {
        print("User \(id): I'm dead!")
    }
}

for i in 1...3 {
    let user = User(id: i)
    print("User \(user.id): I'm in control!")
}
// 类与结构体的区别五:即使类本身是常量,类也允许我们更改变量属性,类不需要mutating使用关键字来更改其数据
class User {
    var name = "Paul"
}

let user = User()
user.name = "Taylor"
print(user.name)

协议

// 协议定义了我们期望数据类型支持的功能,而 Swift 确保我们的代码遵循这些规则
protocol Vehicle {
    func estimateTime(for distance: Int) -> Int
    func travel(distance: Int)
}

struct Car: Vehicle {
    func estimateTime(for distance: Int) -> Int {
        distance / 50
    }

    func travel(distance: Int) {
        print("I'm driving \(distance)km.")
    }
}
// 可以编写一个接受任何符合Vehicle类型的函数
func commute(distance: Int, using vehicle: Vehicle) {
    if vehicle.estimateTime(for: distance) > 100 {
        print("Too slow!")
    } else {
        vehicle.travel(distance: distance)
    }
}

let car = Car()
commute(distance: 100, using: car)
// 协议可以添加属性
protocol Vehicle {
    var name: String { get }  // 标记为get,可能是常量或计算属性
    var currentPassengers: Int { get set } // 标记为get set,可能是变量或带有 getter 和 setter 的计算属性
    func estimateTime(for distance: Int) -> Int
    func travel(distance: Int)
}

扩展

// 扩展允许我们给任何类型添加方法
extension String {
    // Swift 的字符串有一个修剪空格和换行的方法,但它很长,所以我们可以将它变成一个扩展
    func trimmed() -> String {
        self.trimmingCharacters(in: .whitespacesAndNewlines)
    }
}

var quote = "   The truth is rarely pure and never simple   "
let trimmed = quote.trimmed()
// 如果您想直接更改值而不是返回新值,请将您的方法标记为mutating如下所示
extension String {
    mutating func trim() {
        self = self.trimmed()
    }
}

quote.trim()
// 扩展还可以向类型添加计算属性 
extension String {
    var lines: [String] {
        self.components(separatedBy: .newlines)
    }
}
let lyrics = """
But I keep cruising
Can't stop, won't stop moving
print(lyrics.lines.count) // 2

协议扩展

// 对协议进行扩展
extension Collection { // Array、Dictionary和Set都符合Collection协议
    var isNotEmpty: Bool {
        isEmpty == false
    }
}

let guests = ["Mario", "Luigi", "Peach"]

if guests.isNotEmpty {
    print("Guest count: \(guests.count)")
}

可选型

// 可选值表示数据的缺失
// 它们区分值为 0 的整数和根本没有值的整数
let opposites = [
    "Mario": "Wario",
    "Luigi": "Waluigi"
]

let peachOpposite = opposites["Peach"] // 特殊值nil,意味着没有值
// Swift不允许直接使用可选型数据,因为可能是空的,所以我们需要解开可选性数据才能使用它
// 查看内部是否有值,如果有则取出并使用它
// 第一种解包方式(最常见的方式)
if let marioOpposite = opposites["Mario"] {
    print("Mario's opposite is \(marioOpposite)")
}

用guard解包

// 第二种解包方式
// gurad let与if let非常相似,只是逻辑颠倒过来
func printSquare(of number: Int?) {
    guard let number = number else {
        print("Missing input")
        return
    }

    print("\(number) x \(number) is \(number * number)")
}
// 可以在任何条件下使用gurad,包括不解开选项的条件,例如防护数组为空

nil合并

// 第三种解包方式
// 在可选值为空时提供默认值
let tvShows = ["Archer", "Babylon 5", "Ted Lasso"]
let favorite = tvShows.randomElement() ?? "None"

// nil 合并运算符在创建选项的许多地方都很有用
let input = ""
let number = Int(input) ?? 0
print(number)

可选链

let names = ["Arya", "Bran", "Robb", "Sansa"]
let chosen = names.randomElement()?.uppercased() // 如果可选型内部有值,则将其解开,并......
print("Next in line: \(chosen ?? "No one")")

可选型try?

enum UserError: Error {
    case badID, networkFailed
}

func getUser(id: Int) throws -> String {
    throw UserError.networkFailed
}

// 当不关心抛出了什么错误时可以使用 try?,只关心调用是否返回用户
// 如果确切想知道抛出了什么错误就不应该使用try?而是使用do try catch
if let user = try? getUser(id: 23) {
    print("User: \(user)")
}
最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容

  • swift的基础语法 这样吧,先把swift4.0教材的先分享给大家。swift4和swift3的基本上没有多大的...
    请输入账号名阅读 15,703评论 12 60
  • 之前学习swift时的个人笔记,根据github:the-swift-programming-language-i...
    时间已静止阅读 797评论 0 21
  • 面试题 基础 1、class和struct的区别 2、不通过继承,代码服用(共享)的方式有哪些 3、Set独有的方...
    荒漠现甘泉阅读 907评论 0 6
  • 这是我对 Swift 3.0 整理的笔记,主要内容来自于官方文档,添加了一些指针的内容在最后。该笔记由于只是我个人...
    黄穆斌阅读 2,831评论 19 59
  • 写在前面 这是我学习Swift3.0的学习笔记系列的第二篇文章,本篇同第一篇一样,将主要介绍Swift的一些基础语...
    Shaw1211阅读 1,906评论 0 51