欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Swift 5从入门到精通(一、基础语法)

程序员文章站 2022-04-11 16:21:51
...

Hello World

print("Hello World!")
  • 在Swift中,这句话就代表一个程序,和OC不一样,如果你使用Xcode创建一个项目,你会发现没有main函数了,Swift将全局范围内的首句可执行代码作为程序入口(实际上main函数还是存在的,只是Swift对其做了优化)
  • 一句代码尾部不用写分号,但是多句代码写到同一行时必须用分号
  • var定义变量,let定义常量,编译器能自动推断出变量\常量的类型

建议

在学习Swift时,可以使用Xcode自带的Playground,可以快速预览代码效果。Command + Shift + Enter运行整个Playground,

常量,变量

常量只能赋值一次,变量可以多次赋值

// 常量
let maximumNumberOfLoginAttempts = 10
// 变量
var age = 18

常量的值不要求在编译时期确定,但是使用之前必须赋值一次

// 下面这三行代码,在Swift中是合法的,但是在其他一些语言可能就不合法了,这里Swift稍微友好一点,保证常量在使用之前必须赋值一次即可
var a = 100 
a += 100 
let b = a

常量和变量在初始化之前,都不能使用

// 下面代码是错误的:
let name 
print(name)
var age
print(age)

类型注释

声明一个变量名为welcomeMessage的变量,并且该变量可以存储String类型的值

var welcomeMessage: String

注意:
在实践中很少需要编写类型注释。如果在定义的点为常量或变量提供初始值,Swift就可以推断出用于该常量或变量的类型,在welcomeMessage上面的示例中,没有提供初始值,因此该welcomeMessage变量的类型是通过类型注释指定的,而不是从初始值推断出来的。

命名

常量和变量名称几乎可以包含任何字符,包括Unicode字符:
虽然很牛逼,但是不实用。还是老老实实遵守驼峰命名规范吧

let π = 3.14159
let 你好 = "你好世界"
let ???????? = "dogcow"

声明了某种类型的常量或变量后,就无法再使用相同的名称对其进行声明,也无法将其更改为存储其他类型的值。也不能将常量更改为变量或将变量更改为常量。

注意:
如果需要为常量或变量命名为Swift关键字时,则在使用该关键字作为名称时,请在关键字两端加上反引号()。但是,除非绝对没有选择,否则避免将关键字用作名称

let `nil` = 123

注释

// 单行注释

/*
多行注释
*/

Swift有个很友好的地方,可以在多行注释里面嵌套多行注释,这样我们就可以方便,快速的注释掉大块代码

常见数据类型

  • 值类型(value type)
    • 枚举(enum):Optional
    • 结构体(struct):Bool, Int, Float, Double, Character, String, Array, Dictionary, Set
  • 引用类型(reference type)
    • 类(class

这里有一个不一样的地方,就是像Int, Double, Float这些在OC中属于基本数据类型的在Swift中都是属于结构体(struct)类型了,结构体在我们的认识中都是用力存储一些稍微复杂点的内容的, 而这些简单的基本数据类型用的也是结构体,不免会让人担心内存占用是否过大,一个简单的Int是不是就占4个字节,还是更多,其实在Swift里面,已经针对这些做了优化,并且!将这些类型归类于结构体,对Swift后面的一些特性和整体实在是方便太多了。

整数(Int)

Swift提供8位,16位,32位和64位形式的有符号和无符号整数

  • Int8, Int16, Int32, Int64, UInt8, UInt16, Unt32, UInt64
  • 在32bit平台,Int等价于Int32,在64bit平台,Int等价于Int64

你可以使用min和max属性访问每个整数类型的最小值和最大值

let minValue = UInt8.min  // minValue is equal to 0, and is of type UInt8
let maxValue = UInt8.max  // maxValue is equal to 255, and is of type UInt8

除非您需要使用特定大小的整数,否则请始终在代码中Int。这有助于代码的一致性和互操作性。即使在32位平台上,Int也可以在-2,147,483,648和之间存储任何值2,147,483,647,并且对于许多整数范围而言足够大。

注意:
使用UInt只有当你特别需要具有相同大小的平台的本地字大小的无符号整型。如果不是这种情况,那么Int即使已知要存储的值是非负值,也还是首选。始终如一地使用Int整数值有助于代码互操作性,避免了在不同数字类型之间进行转换的需要。

布尔值(Bool)

和OC的YES / NO不同,Swift中为true / false

字符串(String)

和OC区别不大,但是有两个地方值的注意:

  1. Swift明显注重了字符串和字符的区别,这样如果我们仅仅是操作字符,就直接使用字符类型即可
// 这里如果不显示的类型注释为Character类型,那么name会默认是字符串String类型
var name: Character = "jack"

2.Swift增加了子串的概念,主要是针对重复的字符,做了内存优化,这里贴出一段官方的原话:

Swift中的子字符串与字符串具有大多数相同的方法,这意味着您可以像处理字符串一样使用子字符串。但是,与字符串不同,在对字符串执行操作时,只能在短时间内使用子字符串。当您准备长时间存储结果时,可以将子字符串转换为的实例String。
Swift 5从入门到精通(一、基础语法)

字符串相关方法

索引

let greeting = "Guten Tag!"
greeting[greeting.startIndex] // 拿到这个字符串的最开始的字符
// G
greeting[greeting.index(before: greeting.endIndex)] // 拿到字符串的最后一个字符
// !
greeting[greeting.index(after: greeting.startIndex)]// 拿到字符串的第一个字符的后面一个字符
// u
let index = greeting.index(greeting.startIndex, offsetBy: 7) // 拿到字符串的第一个字符后面的第七个字符
greeting[index]
// a

打印字符串的时候,不用像OC那样,还需要占位符。这里直接使用\(),就可以拼接字符串了

for index in greeting.indices {
	// 这里的terminator是print函数的隐形参数,传递一个空字符串,可以避免在控制器打印出来的字符换行问题
    print("\(greeting[index]) ", terminator: "")
}
// Prints "G u t e n   T a g ! "
插入
var welcome = "hello"
// 操作字符
welcome.insert("!", at: welcome.endIndex)
// welcome now equals "hello!"

// 操作字符串
welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there!"
移除
welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there"

let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
// welcome now equals "hello"

数组(Array)

操作数组的方法和字符串大致差不多,多了几个可以判断两个数组是否是包含,相交,等方法

let names = ["jack", "rose", "tom"]

字典(Dictionary)

let person = ["name": "jack", "age": "18", "height": "180"]

下面的代码是错误的

let person = ["name": "jack", "age": 18, "height": 180]

改成这样即可

let person = ["age": 18, "height": 180]

字典的类型必须固定,第一段代码,字典的类是String:String,第三段代码是String: Int
操作字段的方法和数组也差不多,用到的时候查一下即可

元祖(Tuples)

Swift增加了一个特别好用的类型,就是元祖,有点类似我们之前认识的结构体,可以放不同类型在里面,在某些场景,元祖会大大方便我们编码

这里我们模仿一下发送网络请求,服务器可能会返回给我们的内容:

let http404Error = (404, "Not Found")
// http404Error is of type (Int, String), and equals (404, "Not Found")

可以将元组的内容分解为单独的常量或变量,然后像往常一样访问它们:

let (statusCode, statusMessage) = http404Error
print("The status code is \(statusCode)")
// Prints "The status code is 404"
print("The status message is \(statusMessage)")
// Prints "The status message is Not Found"

如果只需要一些元组的值,则_在分解元组时,请用下划线()忽略元组的某些部分:

let (justTheStatusCode, _) = http404Error
print("The status code is \(justTheStatusCode)")
// Prints "The status code is 404"

或者,使用从零开始的索引号访问元组中的各个元素值:

print("The status code is \(http404Error.0)")
// Prints "The status code is 404"
print("The status message is \(http404Error.1)")
// Prints "The status message is Not Found"

定义元组时,可以命名元组中的各个元素:

let http200Status = (statusCode: 200, description: "OK")
print("The status code is \(http200Status.statusCode)")
// Prints "The status code is 200"
print("The status message is \(http200Status.description)")
// Prints "The status message is OK"

注意:
元组对于简单的一组相关值很有用。它们不适合创建复杂的数据结构。如果您的数据结构可能更复杂,则将其建模为类或结构,而不是元组。

类型转换

和OC没什么区别,涉及到一些精度丢失问题,我们直接使用Double类型即可,绝大部分情况都是可以满足的

let int1: UInt16 = 2_000 // swift中,可以使用下划线对很大的数字分隔,增加可读性
let int2: UInt8 = 1
let int3: int1 + UInt(int2)

可选类型(Optionals)

可选类型,我准备放到后面详细的讲一下,这里先简单介绍一下:

在OC里面,没有所谓的可选类型一说,但是我们经常会做一个操作就是会去判断网络请求返回的内容有没有值,或者去操作一个数组时,判断这个数组有没有值,这样才会让接下来的代码更加安全,避免数据越界等问题。

Swift之所以是个安全的语言,在编写代码时,我们就要遵守这个可选类型的规则。编译器会在我们编写代码时,判断出当前定义的变量/常量,是否是确定有值的。如果不确定一定有值,那么这个变量/常量就是个可选类型,如果要使用这个变量/常量,需要对其进行解包

官方原话:

可选的概念在C或Objective-C中不存在。在Objective-C中,最接近的是nil从一种方法返回的能力,该方法原本会返回一个对象,nil意思是“缺少有效的对象”。但是,这仅适用于对象,不适用于结构,基本C类型或枚举值。对于这些类型,Objective-C方法通常返回一个特殊值(例如NSNotFound)以指示不存在值。这种方法假定方法的调用者知道要测试的特殊值,并且记住要进行检查。Swift的可选参数使您可以指示根本不需要任何类型的值,而无需特殊的常量。

下面的代码,我们可以知道,将一个字符串转换成Int类型,如果字符串里面本身就是一串数字,那么是可以成功的转换成Int的,但是如果字符串里面包含了字母或者中文,那么是不能转化成功的:

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// convertedNumber is inferred to be of type "Int?", or "optional Int"

在Xcode中,摁住option键,鼠标移到convertedNumber上,我们可以看到此时convertedNumber常量的类型是Int?
Swift 5从入门到精通(一、基础语法)
如果我们自己想定义一个可选类型,可以显示的为其类型标注

var serverResponseCode: Int? = 404
serverResponseCode = nil

// 这里不对其进行初始化,默认为nil
var surveyAnswer: String?

注意:
只有可选类型才能被赋值为nil,如果不是可选类型,编译器会报错
Swift nil与nilObjective-C中的不一样。在Objective-C中,nil是指向不存在对象的指针。在Swift中,nil它不是指针,而是缺少某种类型的值。可以将任何类型的Optionals 设置为nil,而不仅仅是对象类型。

if语句和强制解包

一旦确定了可选类型确实包含了一个值,我们就可以在可选类型后面加上感叹号(!)来访问它,感叹号有效地表示:“我知道此可选内容肯定具有价值;请使用它。”这称为可选值的强制展开:

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
if convertedNumber != nil {
    print("convertedNumber has an integer value of \(convertedNumber!).")
}

后面会详细说一下可选类型的,现在大致知道怎么解包即可。

总结

以上就是swift的一些基本类型和一些基础语法。相较于OC多了不少特性。比如好用的元祖类型,链式语法的美观性,类型标注,还有很多好用的自带方法。