Swift

一、语法

1. 基本 Variables and Constants,Data Types

var 变量, let 常量

String Int Float/Double Boolean struct
他们都是值类型,存储的都是数据的值
而class是引用类型,存储的是对象的地址。

var s:Int = Int(2)  / var s: Int = 2 
`:Int`,可以不加,系统自动在第一次赋值的时候判断。

Int.random(in: 1...10) //生成随机数

var str : String = “Hello world!”

print() print(str)
print("\(str)"),可以输出变量str的值

pow(2,3) sqrt()  ceil() floor()

2. if判断语句、循环语句,switch语句

If Statement,Switch Statement,For-In Loop,While and Repeat-While Loops

var a = 5
if a < 10 {
    //
} else if a > 100 {
    //
} else {
    //
}

condition 有  if a < 10 && a > 5 
          有  if a > 10 || a < 5

switch chr {
case "a":
    print()
case "b":
    print()
default:
    print()
}

for _ in 1...5{}
for counter in 1...5{} //count不需要提前声明

var counter = 5
while counter > 0{
    counter -= 1 
}

repeat {
    counter -=1
} while counter > 0

3. 方法Functions

func name(){
    //code
}

func name() -> Int{ // Int 为返回值类型
    return 1
}

func name(argumentLabel parameterName: DataType) {
    // some code
}
let sum = name(argumentLable: 5) //lable是参数标签,可以自定义,如果不写,则默认参数名为参数标签,如果不想写参数标签,需要func name(_ parameterName : Int){}

例如func name(_ para1:Int, label para2: Int, para3: Int) -> Int{return 1}

4. Class类 Classes, Subclassing

class Employee {
    var name =""
    var salary = 0
    var role = ""

    func doWork(){
        print("I'm doing my work.")
        salary += 1 
    }
}

var c : Employee = Employee() //This specific Employee that I’ve created in memory is called an object, or an instance of the class, in this case, an instance of the Employee class. 我们创建了一个对象,它是该类的实例,c是对象的引用

c.salary = 1000
c.doWork()

子类
class Manager:Employee(){ //Manager是Employee的子类,可以增加新的属性
    override func doWork(){
        super.doWrok()
        print("I'm doing my big work.")
        salary += 2
    }//子类可以覆盖重写父类的方法,如果想仅仅扩展父类的方法,可以写 super.doWork()
}

5. UIKit

UIKit is an Apple framework that contains many classes for common elements that most iOS apps share, i.e. for labels, buttons, text fields, and images. If we tried building these components from scratch, creating an app would be time-consuming. Thus, UIKit, comes with all of these pre-built elements that we can use in our apps instead.

6. Initializers

class Person {
    var name = ""

    init() { //init 是 关键字

    }

    init(_ name: String) {
        self.name = name //self.name. We use self as like a special variable that refers to the object that’s running this code.
    }
}

var p:person = person("Tim")//跟java一样,如果不写构造方法,那么系统自动添加无参数构造方法,如果自己写了带参数的构造方法,那么无参构造方法就得自己写。

子类也可以继承父类的构造方法。
以下实例是 Overriding Init Functions ,子类覆盖重写父类的构造方法

class Person {
    var name = ""

    init() {

    }

    init(_ name: String) {
        self.name = name
    }
}

class Employee: Person {
    var salary = 0
    var role = ""

    override init(_ name: String) {

        // This is calling the init(_ name: String) function of the Person class
        super.init(name)

        // Additional init code
        self.role = "Analyst"
    }

    func doWork() {
        print("Hi my name is \(name) and I'm doing work")
        salary += 1
    }
}

7. Optionals

//未被初始化,但是是一个Optional类型,为nil
var str: String? (= nil)
print(str)     //输出nil
//未被初始化,也不是Optional类型
var str2: String
print(str2)    //使用时出错

非空使用的时候需要拆包,如果是nil,拆包就会出错
//声明时使用?来指定显示拆包, 拆包时使用!或?拆包
var n1: Int? = 10
print(n1) //Optional(10)\n
print(n1! + 5)    //显式拆包

//声明时使用!来指定隐式拆包, 拆包时直接使用
var n2: Int! = 100
print(n2 + 200)  //隐式拆包

显示拆包和隐式拆包,对于String,自定义类型也一样。 隐式拆包print(str+"hi")

对于自定义类型:

var n1:Person? = nil
var n2:Person! = nil
var n3:Person? = Person()
var n4:Person! = Person()

n1?.a()   //显示拆包,必须用?或!,因为是nil,使用!会报错
//n2.a()  //隐式拆包,虽然nil,但是不报错,只在程序运行后崩溃,可以用?
n3?.a()   //显示拆包,必须用?或!
n4.a()    //隐式拆包,可以直接使用,也可以加!和?

nil 
//This is where optionals come into play, to help declare a variable as “empty”. But how do you define emptiness? We use the nil keyword which stands for empty or nothing. If you don’t want to assign actual data to a variable, you can assign it nil:

var a =nil //但是会报错,需要指定其类型

var a : Int = nil


//If we run this code, we still see an error because integer variables can’t actually store nil. In fact, none of our usual data types (Int, String, etc.) allow nil as a valid value. This is where we use optionals instead by adding a question mark to the data type as follows:

var a: Int? = nil // Int? 是一个整体,Our variable is now an “optional integer,” meaning it could either store an integer as usual or nil.

对于自定义类型
var p: person? = nil

调用的时候必须:
if p != nil{
    print(p!.doWork())//这里必须加`!`. Before you can access the value inside an optional, you have to unwrap the optional, regardless of whether the variable is empty or not.
    //our if statement tells us whether present contains an object or nil, but you cannot access or use the object until you unwrap present.
    //To unwrap `p`, we use an exclamation mark after the variable name, which is analogous to tearing the optional box open, giving us access to whatever’s inside. This would throw an error if the box was empty, because we’re trusting that it in fact carries something. But our if statement verifies that the optional is not empty, so we can safely call surprise on its contents. Because `p` is currently nil, this code should not print anything, meaning our if statement worked as intended.
}


Optional Binding可选绑定

let present: XmasPresent? = nil / XmasPresent() 

// Optional Binding
if let actualPresent = present {
    print(actualPresent.surprise())
}

//其中present是对象的引用,将其赋值给了actualPresent,这个判断语句,就是判断present是否为nil,并且不用拆包。
In the code above, I’m using what’s called an if let statement to check if present is nil or not. If it is nil, the code inside the if statement will not be executed. Otherwise, Swift will automatically unwrap present and assign its contents to a constant called actualPresent. Thus, inside the if statement, you can use actualPresent just like any other object and do not need to unwrap anything. Running the code should print out a random number as expected.

Optional Chaining

let present: XmasPresent? = XmasPresent()

//Optional Chaining
present?.surprise()

在上面的示例中,我在present调用之后添加了问号surprise。问号运算符的工作方式与之前的感叹号几乎相同。唯一的区别是,如果可选结果为nil,则代码不会崩溃,并且整行都将被忽略。这就是为什么我们不需要任何if语句的原因。如果它实际上包含一个对象,那么Swift将照常打开可选对象。在这种情况下,它会调用surprise上present,因为它包含的对象。

8. Properties

Computed Properties

如下,bonus是computed properties

Instead, we can make bonus a computed property which, unlike variables that store values, stores a calculation.

class Manager: Employee {
    var teamSize = 0
    var bonus: Int {
        // This is a computed property
        // When it's accessed, the code in here will run
        // Then, it will return the value

        return teamSize * 1000
    }

    init(_ name: String, _ teamSize: Int) {
        super.init(name)

        self.teamSize = teamSize
    }

    override func doWork() {
        super.doWork()

        print("I'm managing people")
        salary += 2
    }

    func firePeople() {
        print("I'm firing people")
    }
}

9. More Initializers

  1. designated initializers
    class Person {
        var name: String
        var netWorth:Int?
        var gender:String!
    
        init() {
            name = "None"
        }
    }
    
  2. convenience initializer
    swift中,同一个类的不同init方法是不能直接使用self.init()平行调用的。
    必须用关键字convenience修饰的init方法后,才可以使用 self.init(…)
    convenience修饰的init方法就叫便捷初始化器.
    
    class Person {
        var name: String
        var netWorth:Int?
        var gender:String!
    
        // Designated Initializer
        init() {
            name = "None"
        }
    
        // Convenience Initializer
        convenience init(_ gender: String, netWorth: Int) {
            // Call the designated initializer to ensure that the object is ready to go
            self.init()
    
            //Set any other properties or custom code to initialize for this scenario
            self.gender = gender
            self.netWorth = netWorth
        }
    }
    
    // Creating a new Person object
    let a = Person()
    
    // Creating new rich Person objects
    let b = Person("Male", netWorth: 10224334532)
    let c = Person("Female", netWorth: 143211234321)
    

10. Arrays

We denote our array using a pair of square brackets and separating the items “Dog”, “Cat”, and “Bird” with commas. Note that commas are only used in between the actual items. We say that “Dog” is at index 0, “Cat” is at index 1, and “Bird” is at index 2.

var myArray = ["Dog", "Cat", "Bird"]

使用 myArray[0] 来访问。

使用 myArray.count 来访问数组的元素个数
for counter in 0...myArray.count-1 {
    //
}

Regardless, there’s actually an even easier way to write this for loop without using ranges:

var myArray = ["Dog", "Cat", "Bird"]
for item in myArray {
    print(item)
}
Use this method when you only want to work with the elements of the array directly. Otherwise, to write loops that need indexes to, for example, reassign values in an array, you will need to use the for loop with the ranges instead (from our previous example).

Declare an empty array

var emptyArray1 : [String] = []
var emptyArray2 = [String]()
var emptyArray3 : Array<String> = []

数组的数据类型是 [String]、[Int],等等

Add and Remove Items

var myArray = ["Dog", "Cat", "Bird"]

myArray.append("Raccoon")
myArray.insert("Frog", at: 0) // pushes everything back
myArray += ["Frog", "Bear"]

for item in myArray {
    print(item)
}

移除元素
myArray.remove(at: 0) //shift all the other elements down to fill the gap

We can also use `removeAll`, `removeFirst`, `removeLast`, or `removeFirst` number of elements. Pick a certain function depending on what you want to do.

Search for items

myArray.firstIndex(of: "Cat")//which returns the first index where the specified value appears. 

Alternatively, there’s the `lastIndex` method which returns the last index of the item you’re looking for. 

11. Dictionaries

Finally, we will examine another collection type: dictionaries. These are common especially when using data from a remote database or a third party API.

Dictionaries are like special arrays that can be indexed by anything. Arrays allowed us to access data using numeric indexes, and dictionaries allow us to retrieve values using indexes of other data types. How does this work? Well, data is added to dictionaries in key-value pairs. For every value you want to add to your dictionary, you must supply a corresponding key that you would use to access that value later on.

Recall that arrays could only store data of a specific type. Similarly, dictionaries can only use keys and values of a specific type. The key and value types don’t have to match, but all keys should have the same type, as for values.

Declaring a Dictionary

var myDictionary = [String:String]() // [ket data type: value data type]

怎么添加元素
myDictionary["19373"] = "Guo Zhe"
print(myDictionary["19373"])

Notice we got “Optional(“Guo Zhe”)” when printing what we just added. But we never added an optional into our dictionary, so where did this come from? Swift automatically wraps all your dictionary values in an optional type. That way, if you try using a key that doesn’t exist in your dictionary, it can conveniently give you nil in that case. Otherwise, you’ll get your value as an optional which you would unwrap later using any of the methods we’ve discussed before.
//需要注意的是,我们需要`显式解包`来使用这个字典的元素。
print(myDictionary["19373"]!),不能用问号 

myDictionary["19373"] = nil

Iterating Through a Dictionary

myDictionary["SJD 293"] = "Red Ferrari"
myDictionary["UDS 111"] = "Silver Porsche"

for (key, value) in myDictionary {
    print("\(key) is a \(value)")
}

12. 元组 Tuple [/'tʌpl/]

var aTuple = (10, "one")
var aTuple = (index: 10, name: "one") //元素带名的元组
aTuple的类型是 (Int, String)

aTuple.0  ; aTuple.1
aTuple.index  ; aTuple.name

特点:
- 一旦声明,可以改值,但不能添加/删除元素
- 不能更改已经声明的元素名称
- 已声明的名称可以省略名称,但未声明名称的元组,不可添加名称

let (x, y) = aTuple //可以拆分
x // == 10
y // == "one"

取值时可以指定类型,加强类型判断:
let (x, y): (Int, Int) = (1, 2) //正确
let (x, y): (Int, Int) = aTuple //错误,因为第二个值声明为String,与Int不相符

let (x, _) = aTuple //不想处理的值,可以用下划线_代替


做方法的参数
func foo(_ args: (Int, Int, String)) -> Int {
    return args.0
}
let arguments = (4, 3, "hello")
foo(arguments) // 返回 4

元组的元素可以是元组
var aTuple:(Int,(Int,String,Any)) = (1,(2,"3","4"))
元素类型不可以改变,除了Any。


做方法的返回值,返回多个值
func abc() -> (Int, Int, String) {
    return (3, 5, "Xishi")
}
let (a, b, c) = abc()

二、SwiftUI

JSON

JSON(JavaScript Object Notation,JavaScript对象表示法,读作/ˈdʒeɪsən/)

JSON (JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。它基于 ECMAScript (w3c制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。——百度百科


gmm