Swift入门(一)

前言

废话不多说,直接进入正题

Swift基础数据类型

常量和变量

let 来声明常量 ,只能赋值一次,它的值不要求在编译时期确定,但使用之前必须赋值一次
var 来声明变量

image.png
可以在一行中声明多个变量或常量,用逗号分隔
var x = 1, y = 2, z = 3

类型标注,来明确变量或常量能够储存值的类型
var name : String = "Wang"

标识符

常量和变量的名字几乎可以使用任何字符,甚至包括 Unicode 字符
常量和变量的名字不能包含空白字符、数学符号、箭头、保留的(或者无效的) Unicode 码位、连线和制表符。也不能以数字开头,尽管数字几乎可以使用在名字其他的任何地方

let π = 3.1415
let  = "牛马"
print("打印\()")

基本数据类型

整数

Swift 提供了 8,16,32 和 64 位编码的有符号和无符号整数
命名方式:例如 8 位无符号整型 UInt8 ,32 位有符号整型 Int32
可通过 min/max 来访问最小/大值

print(uint8.min)
print(uint8.max)

输出分别是0和255

Int 、UInt 拥有与当前平台的原生字相同的长度,推荐使用

浮点数

Double:64 位浮点数,至少有 15 位数字的精度
Float:32 位浮点数,至少有 6 位数字的精度
在两种类型都可以的情况下,推荐使用 Double 类型。

类型 大小(字节数) 区间值
Int8 1字节 -128 到 127
UInt8 1字节 0 到 255
Inte32 4字节 -2147483648 到 2147483647
UInt32 4字节 0 到 4294967295
Inty64 8字节 -9223372036854775808 到 9223372036854775807
UInt64 8字节 0 到 18446744073709551615
Float 4字节 1.2E-38 到 3.4E+38 (~6 digits)
Double 8字节 2.3E-308 到 1.7E+308 (~15 digits)

Bool

Swift 是类型安全的 ,判断语句中不允许传入非布尔值
image.png

正确代码:

let i = 1
if i == 1 {
    print(i)
}

类型别名

为已存在类型定义一个更具有表达性的名字

typealias SoundVolume = UInt8 // 音量值
let volume : SoundVolume = 5

字面量

简洁明了的指出自己的类型并且能为变量赋值的值

// 布尔
let bool = true //取反是false
// 整数
let intDecimal = 17  //十进制
let intBinary = 0b10001 //二进制
let intOctal = 0o21  //八进制
let intHexadecimal = 0x11 //十六进制
// 浮点数
let doubleDecimal = 125.0 //十进制,等价于1.25e2,0.0125等价于1.25e-2
let doubleHexadecimal1 = 0xFp2 //十六进制,意味着15x2^2,相当于十进制的60.0
let doubleHexadecimal2 = 0xFp-2 //十六进制,意味着15x2^-2,相当于十进制的3.75
// 字符串
let string = "字符串"
// 字符(可存储ASCII字符、Unicode字符)
let character: Character = ""
// 数组
let array = [1, 3, 5, 7, 9]
// 字典
let dictionary = ["height" : 180, "age" : 18]

整数和浮点数可以添加额外的零或者添加下划线_来增强可读性

let num = 100_0000
let num2 = 1_000_000.000_000_1
let num3: Double = 000123.456

元组

元组把多个值合并成单一的复合型的值
元组内的值可以是任何类型,而且可以不必是同一类型
元组中的每一个元素可以指定对应的元素名称
如果没有指定名称的元素也可以使用下标的方式来引用

let error = (errorCode: 404, "错误")
print(error.errorCode)
print(error.1)
// 输出:404 错误

元组修改

var 定义可变元组,let 定义不可变元组
不管是可变还是不可变元组,元组在创建后就不能增加和删除元素
可以对可变元组的元素进行修改,但是不能改变其类型

var error = (errorCode: 404, errorMsg: "错误")
error.errorCode = 2
// error.errorCode = "2"  报错:'Cannot assign value of type 'String' to type 'Int''

any 类型可以改为任何类型

var error:(errorCode: Any, errorMsg: String) = (errorCode: 404, errorMsg: "错误")
error.errorCode = 2
error.errorCode = "2"

元组拆解

将一个元组的内容分解成单独的常量或变量

let error = (404, "错误")
let (errorCode, errorMsg) = error
print(errorCode)
print(errorMsg)

如果只需要使用其中的一部分数据,不需要的数据可以用下滑线 _ 代替

let error = (404, "错误")
let (errorCode, _) = error
print(errorCode)

元组作为函数返回值

使用元组为函数返回多个值

func request(url: String) -> (errorCode: Int, errorMsg: String) {
    return (404, "错误")
}

Optional

在类型名称后面加个问号?来定义一个可选项
可选项是对其他类型的一层包装,可以将它理解为一个盒子

  • 如果为nil,那么它是个空盒子
  • 如果不为nil,那么盒子里装的是:被包装类型的数据
  • 在 Swift 中,nil 不是指针,而是值缺失的一种特殊类型,任何类型的可选项都可以设置成 nil 而不仅仅是对象类型
    image.png
var age: Int? //默认就是nil
age = 10
age = nil

强制解包

如果要从可选项中取出被包装的数据,需要使用感叹号!进行强制解包

var age: Int? = 10
let ageInt: Int = age!
ageInt += 10

对值为nil的可选项进行强制解包,会产生运行时错误
image.png

判断可选项是否包含值

let num = Int("123")
if num != nil {
    print("字符串转换整数成功:\(num!)")
}

var str: String? = "abc"
if str != nil {
    print(str!)
}

可选项绑定

可以使用可选项绑定来判断可选项是否包含值
如果包含就自动解包,把值赋给一个临时常量(let)或者变量(var),并返回true,否则返回false

var str: String? = "abc"
if let number = Int("123"), let tempStr = str {
    print(tempStr,number)
}
else {
    print("nil")
}

隐式解包

有些可选项一旦被设定值之后,就会一直拥有值,在这种情况下,就可以去掉检查的需求, 也不必每次访问的时候都进行解包
在声明的类型后边添加一个叹号! 而非问号?

var string: String! = "efg"
if let tempString = string {
    print(tempString)
}

多重可选项

可选项(盒子)后面加问号?
如果可选项不为nil,返回一个可选项,否则返回nil

var str: String? = "efg"
let count = str?.count
if count != nil {
    let lastIndex = count! - 1
    print(lastIndex)
}

var num1: Int? = 10
var num2: Int?? = num1
var num3: Int?? = 10
print(num2 == num3) //true

可选项打印

可选项在字符串插值或者直接打印时,编译器会发出警告
image.png

至少有3种方法消除警告

var age: Int? = 10
print("年龄:\(age!)")
// 年龄:10
print("年龄:\(String(describing: age))")
// 年龄:Optional(10)
print("年龄:\(age ?? 0)")
// 年龄:10

字符串

初始化空串

  • 字面量
var emptyString = ""
  • 初始化器语法
var emptyString = String()
// isEmpty检查是否为空字符串
if emptyString.isEmpty {
    print("empty")
}

多行字面量

  • 如果你想要使用换行符来让你的代码易读,却不想让换行符成为字符串的值,那就在那些行的末尾使用反斜杠\
  • 如果你在某行的空格超过了结束的双引号( """ ),那么这些空格会被包含
let mutableStr = """
    当你的代码中在多行字符串字面量里包含了换行,\
那个换行符同样会成为字符串里的值。
    如果你想要使用换行符来让你的代码易读,
    却不想让换行符成为字符串的值,
    那就在那些行的末尾使用反斜杠
"""
print(mutableStr)

字符串里的特殊字符

  • 转义特殊字符 \0 (空字符), \\ (反斜杠), \t (水平制表符), \n (换行符), \r(回车符), \" (双引号) 以及\ ' (单引号)
let str = "老实说:\"哈哈。\"\t\'呵呵\'"
  • 任意的 Unicode 标量,写作 \u{n},里边的 n 是一个 1-8 位的16 进制数字,其值是合法 Unicode 值
let uniStr = "\u{24}"  // $
let uniStr2 = "\u{2665}" // ♥
let uniStr3 = "\u{1F496}"// 
  • 可以在多行字符串字面量中包含双引号( " )而不需转义。要在多行字符串中包含文本 """ ,转义至 少一个双引号
let mutableStr = """
可以在多行字符串字面量中包含双引号( " )而不需转义。要在多行字符串中包含文本 "\"" ,转义至少一个双引号
"""

扩展字符串分隔符

把字符串放在双引号( " )内并由井号( # )包裹
在字符串字面量中放置扩展分隔符来让其中包含的特殊字符不生效

let str = "Line 1\nLine 2"  //正常换行
let str2 = #"Line 1\nLine 2"#  //Line 1\nLine 2 换行失效

如果字符串里有" # 需要显示则首尾需要两个 ##
如果需要字符串中某个特殊符号的效果,使用匹配你包裹的井号数量的井号并在前面写转义符号 \

let str3 = ##"Line 1\#nLine 2"\nLine 3\##nLine 4"##
/* 打印结果:
   Line 1\#nLine 2"\nLine 3
   Line 4
*/

可变与不可变字符串
image.png

字符串是值类型

  • String 值在传递给方法或者函数的时候会被复制过去
  • 赋值给常量或者变量的时候也是一样
  • Swift 编译器优化了字符串使用的资源,实际上拷贝只会在确实需要的时候才进行
var str: String = "abc"
var str1 = str
print(str == str1)   // true
str += "def"
print(str)     // abcdef
print(str1)    // abc
print(str == str1)   // false

Character 类型

  • for-in 循环遍历 String 中的每一个独立的
  • String 值可以通过传入 Character 数组来构造
let catCharacter: [Character] = ["C", "A", "T", ""]
let catWord: String = String(catCharacter)
print(catWord)

字符串拼接

var str2 = "新年" + "快乐"
print(str2)    //新年快乐
str2 += "!"
print(str2)   // 新年快乐!
str2.append("")
print(str2)   // 新年快乐!

字符串插值

  • 字符串插值是一种从混合常量、变量、字面量和表达式的字符串字面量构造新 String 值的方法
  • 每一个你插入到字符串字面量的元素都要被一对圆括号()包裹,然后使用反斜杠\前缀
  • 类似于 NSString 的 stringWithFormat 方法,但是更加简便,更强大
let age = 3
let desc = "\(age) 它的2.5倍是:\(Double(age) * 2.5)"

要在使用扩展分隔符的字符串中使用字符串插值,在反斜杠后使用匹配首尾井号数量的井号

print(#"它的2.5倍是:\(Double(age) * 2.5)"#) // 它的2.5倍是:\(Double(age) * 2.5)
print(#"它的2.5倍是:\#(Double(age) * 2.5)"#) // 它的2.5倍是:7.5

字符串索引

  • 每一个 String 值都有相关的索引类型, String.Index,它相当于每个 Character在字符串中的位置
  • 使用 index(before:) 和 index(after:) 方法来访问给定索引的前后
let str: String = "abcdefg"
print(str.startIndex)   // Index(_rawBits: 1)
print(str[str.startIndex])  // a
print(str.endIndex)    //  Index(_rawBits: 458753)
print(str[str.index(before: str.endIndex)])  // g
print(str[str.index(after: str.startIndex)])  //b

// 如果 String 为空,则 startIndex 与 endIndex 相等
let str2: String = ""
print(str2.startIndex == str2.endIndex)  // true
  • 要访问给定索引更远的索引,你可以使用 index(_:offsetBy:)
let str: String = "abcdefg"
let index = str.index(str.startIndex, offsetBy: 5)
print(str[index])       //  f
let index2 = str.index(str.startIndex, offsetBy: 9) // 越界崩溃
  • 使用 indices 属性来访问字符串中每个字符的索引
for index in str.indices {
    print(index)
}

插入 & 删除

var welcome = "hello "
welcome.insert("!", at: welcome.endIndex)      //hello !
welcome.insert(contentsOf: "word", at: welcome.index(before: welcome.endIndex)  
print(welcome)  // hello word!

welcome.remove(at: welcome.index(before: welcome.endIndex))
print(welcome) // hello word
let range = welcome.index(welcome.endIndex, offsetBy: -5)..

子字符串

  • 使用下标或者类似 prefix(_:) 的方法得到的子字符串是 Substring 类型
  • Substring 拥有 String 的大部分方法
  • 子字符串重用一部分原字符串的内存
var welcome = "hello, word!"
let subStr = welcome.prefix(5)
print(subStr)
let index = welcome.index(welcome.startIndex, offsetBy: 7)
let endStr = welcome[index..

字符串比较

var welcome = "hello, word!"
var welcome1 = "hello"
print(welcome == welcome1)        // false
print(welcome.hasPrefix("hello"))  // true
print(welcome.hasSuffix("word!")) // true

你可能感兴趣的:(Swift入门(一))