2021-07-22 学习SWFIT 基础语法

对照网站,从基础学起,这里记录一下有一些其他语言没遇到过的知识
教程地址 https://www.hackingwithswift.com/100
基本上代码都来自教程,为了适合我复习改了少少。
此文对应教程中 day1-day12,day13-day15没有新内容,也算在这里啦

一、变量(Variable)

1、声明多行字符串

var burns = """
The best laid schemes
o'nice an ' men
gang aft agley
"""

2、整型和双精度数字
因为“类型安全”,整型和双精度不能进行数字操作

var a = 1
var b = 1.1
var c = a + b //这里会报错 
var d = 1 + 1.1 // 这里不会报错 为什么??

3、字符插值

var forecast = "Today's weather will be \(weather)"

二,复杂数据类型

1、数组、集、元组、字典(Array,Set,Tuples,Dictionary)

var arr = [1,2,3,4]
var set = Set([1,2,3,4])
var name = (first:"Taylor",last:"Swift")
var heights = ["taylor":1.72,"Ed":1.73]

//读取字典时,可以传个default,以确保不会返回nil
heights["google"]//nil
heights["google",default:1.70]//1.70

创建一个新的对象

//新字典
var teams = [String:String]()
teams["paul"] = "Red"]
//或
var teams = Dictionary<String,String>()
teams["paul"] = "Red"]

//新数组
var results = [Int]()
results[0] = 0
//或
var results = Array<Int>()
result[0] = 0

//而集合没有简化写法,只能用Set
var words = Set<String>()
  • 数组/字典长度是可变的
  • 集合会忽略重复的值
  • 元组定义之后不可以添加新的类型,只能修改值, 对吗?

2、枚举(Enum)

enum Result {
   case success
   case failure
}

let res = Result.failure

枚举关联值 , 好像一个方法

enum Activity{
   case hored
   case running(destination:String)
   case taking(topic:String)
   case singing(volume:Int)
}

let talking = Activity.talking(topic:"football")

三、运算符 和 条件 (Operators,Condition)

  • 运算符 加减乘除余 += -= *= /=
  • 条件 if else 和 switch 和其他语言一样用法

范围运算符 ..< 和 ...

let score = 85

switch score {
    case 0..<50:
    print (" you failed badly.")
    case 50..<80:
    print (" you did OK.")
  default:
    print("You did great!")
}

数组也可以用+和+=

var songs = ["Shake it Off", "You Belong with Me", "Love Story"]
var songs2 = ["Today was a Fairytale", "Welcome to New York", "Fifteen"]
var both = songs + songs2
both += ["Everything has Changed"]

四、循环(Loop)

  • for循环
    for循环中的号 ,当循环的变体不被引用的时候,会要求声明为
for _ in 1...5 {
  print("do for loop")
}
  • while repeate ... while 和其他语言用法一样

五、函数(Function)

  • 函数每个参数可以使用两个标签,第一个给外部使用,如果想省略就写成_,第二个标签给函数做内部引用
func great(_ person:String,nicely:Bool=true){
    if nicely == true {
        print("hello, \(person)!")
    }else{
        print ("oh no, it's \(person)")
    }
 }

可变参数 要求在声明的类型后加三个点

func square(numbers:Int...){
    for num in numbers{
        print ("squared is \(num*num)")
    }
}

抛出错误 要求在do语句块中调用,且调用前要加关键字try

//先定义一个Error枚举
enum PasswordError:Error{
  case obvious
}

//
func checkPassword(_ password:String) throws -> Bool {
    if password == "" || password == "password" {
        throw PasswordError.obvious
    }
    return true
}

do{
  try checkPassword(password:"password")
  print ("pw is good")
}catch{
  print("can't use pw")
}
  • 输入参数inout,调用输入参数时,要在变量前加“&”
func doubleInplace(number: inout Int){
  num *= 2
}

var num = 10
doubleInPlace(number:&num)

六、闭包 (closure syntax) D6D7

  • 基本闭包
  • 闭包的函数体直接跟在=号之后,没有func关键字
  • 包含参数的括号放在大括号内,并且要带一个in 关键字. in关键字分隔参数和函数主体
  • 返回值类型声明也需要放在in之前
let payment = {(user:String,amount:Int)->String in 
    return "user : \(user) , amount: \(amount)"
}
  • 尾随闭包? Trailing closure syntax
    如果一个函数的最后一个参数是闭包,可以不用像传入参数一样传递闭包
func travel (action:()->void) {
    print ("I'm getting ready to go.")
    action()
    print("I arrived")
 }

//以下两种写法打印是一样的
let driving = {
  print ("driving ...")
}
travel(action:driving)

//直接尾随闭包 ()也是可以省略的,这里为了可以看到参数应该在哪
travel(){
    print("driving 2 ....")
}

闭包速记语法

func travel (action:(String)->String) {
    print ("I'm getting ready to go.")
    let desc = action()
    print(desc)
    print("I arrived")
 }

//尾随闭包写法
travel { (place:String)->String in
     return "I'm going to \(place) in my car"
}
//简化写法
travel { place in
    return "I'm going to \(place) in my car"
}
//用速记$0替换参数
travel {
    return "I'm going to \($0) in my car"
}

闭包捕获参数

func travel() -> (String)->Void {
    var counter = 1    
     return {
         print(" \(counter) , I'm going to \($0)")
         counter += 1
    }
}

let target= travel()
target("Beijing")
result("Shanghai")
result("Guangzhou")

//可以看到打印,counter是一直变化的
1.I'm going to Beijing
2.I'm going to Shanghai
3.I'm going to Guangzhou

七、结构体(Struct) D8D9

结构体是值类型

  • 结构体和元组有什么区别?元组就是一个匿名结构体?
  • 结构体和类有什么区别?结构体是常量?
  • 计算属性
  • 观察者 willSet didSet
struct Progress {
    var task:String
    var state:Bool {
          return task == ""
    }
    var amount:Int {
       didSet{
            print("now \(amount)% complete")
        }
    }

    //结构体内还可以有方法
    func getState()->Int{
          return amount>=100?1:0
    }
}

var pro = Progress(task:"Loading Data",amount:0)
pro.amount = 30
pro.amount = 60
pro.amount = 100
  • 变异方法
    结构体创建的时候是常量不能改变属性,任何结构体的方法试图改变任何属性,都必标记成mutating
    未标记mutating的方法不能调用已标记mutating的方法
struct Person {
  var name
  mutating func makeAnonymous(){
    name = "Anonymous"
  }
}

var person = Person(name:"Ed")
person.makeAnonymous()
  • 字符串/整数/数组/字典等swift的核心类都是结构体

  • 结构体未定义init()方法的时候,可以用成员初始化器,定义了之后,只能用init的参数

//  这种可以用成员初始化器
struct Employee {
    var name: String
    var yearsActive = 0
}
let roslin = Employee(name: "Laura Roslin")
let adama = Employee(name: "William Adama", yearsActive: 45)

// 但是有init方法之后,只能用init的参数
struct Employee {
    var name: String
    var yearsActive = 0

    init(str:String) {
        self.name = "Anonymous"
        print("Creating an anonymous employee…")
    }
}

let anon = Employee(str:"unknow");

//init方法放在Extension中时,又可以用成员初始化器
struct Employee {
    var name: String
    var yearsActive = 0   
}
extension Employee {
    init() {
        self.name = "Anonymous"
        print("Creating an anonymous employee…")
    }
}

let roslin = Employee(name: "Laura Roslin")
let anon = Employee()
  • lazy 在调用的时候执行初始化,并在初始化完成后保存这个值
  • 静态属性和访问控制和其他语言一样

八、类(Class) D10

类和结构有五个重要区别:

  • 类不带有合成的成员初始化器。
  • 一个类可以继承另一个类,获得它的属性和方法。
  • 结构的副本总是唯一的,而类的副本实际上指向相同的共享数据。
  • 类有析构器(deinit),它们是在类的实例被销毁时调用的方法,但结构没有。
  • 常量类中的变量属性可以自由修改,但是常量结构体中的变量属性不能。

变量类可以改变变量属性
常量类可以改变变量属性
变量结构可以改变变量属性
常量结构不能改变变量属性

类、继承 和其他语言一样,略了

九、协议和扩展 (Protocol,Extension)

协议和Java系的“接口(interface)”一样 略

  • 扩展允许您向现有类型添加方法,使它们执行最初设计时不打算执行的操作
    不允许在扩展中添加存储属性,因此您必须改用计算属性
extension Int {
    func squared() -> Int {
        return self * self
    }
}
  • 协议扩展可以使所有符合协议的类都得到您的更改
extension Collection {
    func summarize() {
        print("There are \(count) of us:")

        for name in self {
            print(name)
        }
    }
}

//数组和集合都遵循Collection协议
let pythons = ["Eric", "Graham", "John", "Michael", "Terry", "Terry"]
let beatles = Set(["John", "Paul", "George", "Ringo"])
pythons.summarize()
beatles.summarize()

十、可选项(Optionals)

可选项允许我们表示某些数据的缺失。

  • 展开可选项
    可选项的一个最重要的特性是 Swift 不会让我们在没有展开它们的情况下使用它们。
    这为我们的应用程序提供了大量的保护,因为它消除了不确定性:当你处理一个字符串时,你知道它是一个有效的字符串,当你调用一个返回整数的函数时,你知道它立即是安全的采用。当你的代码中确实有可选项时,Swift 将始终确保你正确处理它们——检查和解包它们,而不是仅仅将不安全的值与已知的安全数据混合在一起。

if let ... 展开可选项

func getUsername() -> String? {
    return "Taylor"
}

if let username = getUsername() {
    print("Username is \(username)")
} else {
    print("No username")
}

guard let 展开可选项

func greet(_ name: String?) {
    guard let unwrapped = name else {
        print("You didn't provide a name!")
        return
    }

    print("Hello, \(unwrapped)!")
}

强制展开
Optionals 表示可能存在也可能不存在的数据,但有时您可以确定某个值不为零。
在这些情况下,Swift 允许您强制解包可选类型:将其从可选类型转换为非可选类型。

let str = "5"
let num = Int(str)!

隐式解包

let num:Int! = nil

nil 合并 , 给可能为nil的表达式添加一个默认值,从而展开可选项

func username(for id: Int) -> String? {
    if id == 1 {
        return "Taylor Swift"
    } else {
        return nil
    }
}
let user = username(for: 15) ?? "Anonymous"

可选链

let names = ["Vincent": "van Gogh", "Pablo": "Picasso", "Claude": "Monet"]
//当names.first为nil时,不会进行后面的操作
let beatle = names.first?.uppercased()
let surnameLetter = names["Vincent"]?.first?.uppercased() ?? "?"

可选try

enum PasswordError: Error {
    case obvious
}

func checkPassword(_ password: String) throws -> Bool {
    if password == "password" {
        throw PasswordError.obvious
    }

    return true
}

//常规do...try...catch
do {
    try checkPassword("password")
    print("That password is good!")
} catch {
    print("You can't use that password.")
}

//try?
if let result = try? checkPassword("password") {
    print("Result was \(result)")
} else {
    print("D'oh.")
}

//确认不会报错时可以,try!
try! checkPassword("sekrit")
print("OK!")

可以失败的初始化?

struct Employee {
    var username: String
    var password: String

    init?(username: String, password: String) {
        guard password.count >= 8 else { return nil }
        guard password.lowercased() != "password" else { return nil }

        self.username = username
        self.password = password
    }
}
let tim = Employee(username: "TimC", password: "app1e")
let craig = Employee(username: "CraigF", password: "ha1rf0rce0ne")

类型转换 as?

class Person {
    var name = "Anonymous"
}

class Customer: Person {
    var id = 12345
}

class Employee: Person {
    var salary = 50_000
}

let customer = Customer()
let employee = Employee()
let people = [customer, employee]

for person in people {
    if let customer = person as? Customer {
        print("I'm a customer, with id \(customer.id)")
    } else if let employee = person as? Employee {
        print("I'm an employee, earning $\(employee.salary)")
    }
}

思考

  • swift 的基类是NSObject吗,如Java的Object ?
    swift 没有像Java Object一样的唯一基类,有多个协议可以看成根类
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • swift是Apple在2014年6月WWDC发布的全新编程语言,中文名和LOGO是雨燕,Swift是由Chris...
    coder_feng阅读 641评论 0 4
  • 简介 特点(1)优于OC,快速,安全(2)取消了预编译指令包括宏定义(OC用的太多了)(3)取消了OC指针和不安全...
    洛洛爱吃肉阅读 901评论 0 3
  • 常量&变量 简单体验 阶段性小结var 定义变量,设置之后可以修改let 定义常量,设置之后不可以修改语句末尾不用...
    年轻在于折腾阅读 341评论 0 1
  • Swift基础语法文章汇总[https://www.jianshu.com/p/4c260bb9782d] 本文简...
    iOS之文一阅读 654评论 0 2
  • >1swift来历:2014年推出,具有安全,现代,互动,快速的特点. >2playground可以用来测试,学习...
    uniapp阅读 251评论 0 0