前言
廢話不多說,直接進(jìn)入正題
Swift基礎(chǔ)數(shù)據(jù)類型
常量和變量
let 來聲明常量 蕾管,只能賦值一次事镣,它的值不要求在編譯時(shí)期確定,但使用之前必須賦值一次
var 來聲明變量
var x = 1, y = 2, z = 3
類型標(biāo)注,來明確變量或常量能夠儲(chǔ)存值的類型
var name : String = "Wang"
標(biāo)識(shí)符
常量和變量的名字幾乎可以使用任何字符采够,甚至包括 Unicode 字符
常量和變量的名字不能包含空白字符肄方、數(shù)學(xué)符號(hào)、箭頭蹬癌、保留的(或者無(wú)效的) Unicode 碼位权她、連線和制表符。也不能以數(shù)字開頭冀瓦,盡管數(shù)字幾乎可以使用在名字其他的任何地方
let π = 3.1415
let ???? = "牛馬"
print("打印\(????)")
基本數(shù)據(jù)類型
整數(shù)
Swift 提供了 8伴奥,16,32 和 64 位編碼的有符號(hào)和無(wú)符號(hào)整數(shù)
命名方式:例如 8 位無(wú)符號(hào)整型 UInt8 翼闽,32 位有符號(hào)整型 Int32
可通過 min/max 來訪問最小/大值
print(uint8.min)
print(uint8.max)
輸出分別是0和255
Int 拾徙、UInt 擁有與當(dāng)前平臺(tái)的原生字相同的長(zhǎng)度,推薦使用
浮點(diǎn)數(shù)
Double:64 位浮點(diǎn)數(shù)感局,至少有 15 位數(shù)字的精度
Float:32 位浮點(diǎn)數(shù)尼啡,至少有 6 位數(shù)字的精度
在兩種類型都可以的情況下,推薦使用 Double 類型询微。
類型 | 大醒虏t。ㄗ止?jié)數(shù)) | 區(qū)間值 |
---|---|---|
Int8 | 1字節(jié) | -128 到 127 |
UInt8 | 1字節(jié) | 0 到 255 |
Inte32 | 4字節(jié) | -2147483648 到 2147483647 |
UInt32 | 4字節(jié) | 0 到 4294967295 |
Inty64 | 8字節(jié) | -9223372036854775808 到 9223372036854775807 |
UInt64 | 8字節(jié) | 0 到 18446744073709551615 |
Float | 4字節(jié) | 1.2E-38 到 3.4E+38 (~6 digits) |
Double | 8字節(jié) | 2.3E-308 到 1.7E+308 (~15 digits) |
Bool
Swift 是類型安全的 ,判斷語(yǔ)句中不允許傳入非布爾值正確代碼:
let i = 1
if i == 1 {
print(i)
}
類型別名
為已存在類型定義一個(gè)更具有表達(dá)性的名字
typealias SoundVolume = UInt8 // 音量值
let volume : SoundVolume = 5
字面量
簡(jiǎn)潔明了的指出自己的類型并且能為變量賦值的值
// 布爾
let bool = true //取反是false
// 整數(shù)
let intDecimal = 17 //十進(jìn)制
let intBinary = 0b10001 //二進(jìn)制
let intOctal = 0o21 //八進(jìn)制
let intHexadecimal = 0x11 //十六進(jìn)制
// 浮點(diǎn)數(shù)
let doubleDecimal = 125.0 //十進(jìn)制撑毛,等價(jià)于1.25e2书聚,0.0125等價(jià)于1.25e-2
let doubleHexadecimal1 = 0xFp2 //十六進(jìn)制,意味著15x2^2藻雌,相當(dāng)于十進(jìn)制的60.0
let doubleHexadecimal2 = 0xFp-2 //十六進(jìn)制雌续,意味著15x2^-2,相當(dāng)于十進(jìn)制的3.75
// 字符串
let string = "字符串"
// 字符(可存儲(chǔ)ASCII字符胯杭、Unicode字符)
let character: Character = "??"
// 數(shù)組
let array = [1, 3, 5, 7, 9]
// 字典
let dictionary = ["height" : 180, "age" : 18]
整數(shù)和浮點(diǎn)數(shù)可以添加額外的零或者添加下劃線_來增強(qiáng)可讀性
let num = 100_0000
let num2 = 1_000_000.000_000_1
let num3: Double = 000123.456
元組
元組把多個(gè)值合并成單一的復(fù)合型的值
元組內(nèi)的值可以是任何類型驯杜,而且可以不必是同一類型
元組中的每一個(gè)元素可以指定對(duì)應(yīng)的元素名稱
如果沒有指定名稱的元素也可以使用下標(biāo)的方式來引用
let error = (errorCode: 404, "錯(cuò)誤")
print(error.errorCode)
print(error.1)
// 輸出:404 錯(cuò)誤
元組修改
var 定義可變?cè)M,let 定義不可變?cè)M
不管是可變還是不可變?cè)M做个,元組在創(chuàng)建后就不能增加和刪除元素
可以對(duì)可變?cè)M的元素進(jìn)行修改鸽心,但是不能改變其類型
var error = (errorCode: 404, errorMsg: "錯(cuò)誤")
error.errorCode = 2
// error.errorCode = "2" 報(bào)錯(cuò):'Cannot assign value of type 'String' to type 'Int''
any 類型可以改為任何類型
var error:(errorCode: Any, errorMsg: String) = (errorCode: 404, errorMsg: "錯(cuò)誤")
error.errorCode = 2
error.errorCode = "2"
元組拆解
將一個(gè)元組的內(nèi)容分解成單獨(dú)的常量或變量
let error = (404, "錯(cuò)誤")
let (errorCode, errorMsg) = error
print(errorCode)
print(errorMsg)
如果只需要使用其中的一部分?jǐn)?shù)據(jù)滚局,不需要的數(shù)據(jù)可以用下滑線 _ 代替
let error = (404, "錯(cuò)誤")
let (errorCode, _) = error
print(errorCode)
元組作為函數(shù)返回值
使用元組為函數(shù)返回多個(gè)值
func request(url: String) -> (errorCode: Int, errorMsg: String) {
return (404, "錯(cuò)誤")
}
Optional
在類型名稱后面加個(gè)問號(hào)?來定義一個(gè)可選項(xiàng)
可選項(xiàng)是對(duì)其他類型的一層包裝顽频,可以將它理解為一個(gè)盒子
- 如果為nil藤肢,那么它是個(gè)空盒子
- 如果不為nil,那么盒子里裝的是:被包裝類型的數(shù)據(jù)
-
在 Swift 中冲九,nil 不是指針谤草,而是值缺失的一種特殊類型跟束,任何類型的可選項(xiàng)都可以設(shè)置成 nil 而不僅僅是對(duì)象類型
var age: Int? //默認(rèn)就是nil
age = 10
age = nil
強(qiáng)制解包
如果要從可選項(xiàng)中取出被包裝的數(shù)據(jù)莺奸,需要使用感嘆號(hào)!進(jìn)行強(qiáng)制解包
var age: Int? = 10
let ageInt: Int = age!
ageInt += 10
對(duì)值為nil的可選項(xiàng)進(jìn)行強(qiáng)制解包冀宴,會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤判斷可選項(xiàng)是否包含值
let num = Int("123")
if num != nil {
print("字符串轉(zhuǎn)換整數(shù)成功:\(num!)")
}
var str: String? = "abc"
if str != nil {
print(str!)
}
可選項(xiàng)綁定
可以使用可選項(xiàng)綁定來判斷可選項(xiàng)是否包含值
如果包含就自動(dòng)解包灭贷,把值賦給一個(gè)臨時(shí)常量(let)或者變量(var),并返回true略贮,否則返回false
var str: String? = "abc"
if let number = Int("123"), let tempStr = str {
print(tempStr,number)
}
else {
print("nil")
}
隱式解包
有些可選項(xiàng)一旦被設(shè)定值之后甚疟,就會(huì)一直擁有值,在這種情況下逃延,就可以去掉檢查的需求览妖, 也不必每次訪問的時(shí)候都進(jìn)行解包
在聲明的類型后邊添加一個(gè)嘆號(hào)! 而非問號(hào)?
var string: String! = "efg"
if let tempString = string {
print(tempString)
}
多重可選項(xiàng)
可選項(xiàng)(盒子)后面加問號(hào)?
如果可選項(xiàng)不為nil揽祥,返回一個(gè)可選項(xiàng)讽膏,否則返回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
可選項(xiàng)打印
可選項(xiàng)在字符串插值或者直接打印時(shí),編譯器會(huì)發(fā)出警告至少有3種方法消除警告
var age: Int? = 10
print("年齡:\(age!)")
// 年齡:10
print("年齡:\(String(describing: age))")
// 年齡:Optional(10)
print("年齡:\(age ?? 0)")
// 年齡:10
字符串
初始化空串
- 字面量
var emptyString = ""
- 初始化器語(yǔ)法
var emptyString = String()
// isEmpty檢查是否為空字符串
if emptyString.isEmpty {
print("empty")
}
多行字面量
- 如果你想要使用換行符來讓你的代碼易讀拄丰,卻不想讓換行符成為字符串的值府树,那就在那些行的末尾使用反斜杠\
- 如果你在某行的空格超過了結(jié)束的雙引號(hào)( """ ),那么這些空格會(huì)被包含
let mutableStr = """
當(dāng)你的代碼中在多行字符串字面量里包含了換行料按,\
那個(gè)換行符同樣會(huì)成為字符串里的值奄侠。
如果你想要使用換行符來讓你的代碼易讀,
卻不想讓換行符成為字符串的值载矿,
那就在那些行的末尾使用反斜杠
"""
print(mutableStr)
字符串里的特殊字符
- 轉(zhuǎn)義特殊字符 \0 (空字符)垄潮, \\ (反斜杠), \t (水平制表符)闷盔, \n (換行符)弯洗, \r(回車符), \" (雙引號(hào)) 以及\ ' (單引號(hào))
let str = "老實(shí)說:\"哈哈馁筐。\"\t\'呵呵\'"
- 任意的 Unicode 標(biāo)量涂召,寫作 \u{n},里邊的 n 是一個(gè) 1-8 位的16 進(jìn)制數(shù)字敏沉,其值是合法 Unicode 值
let uniStr = "\u{24}" // $
let uniStr2 = "\u{2665}" // ?
let uniStr3 = "\u{1F496}"http:// ??
- 可以在多行字符串字面量中包含雙引號(hào)( " )而不需轉(zhuǎn)義果正。要在多行字符串中包含文本 """ 炎码,轉(zhuǎn)義至 少一個(gè)雙引號(hào)
let mutableStr = """
可以在多行字符串字面量中包含雙引號(hào)( " )而不需轉(zhuǎn)義。要在多行字符串中包含文本 "\"" 秋泳,轉(zhuǎn)義至少一個(gè)雙引號(hào)
"""
擴(kuò)展字符串分隔符
把字符串放在雙引號(hào)( " )內(nèi)并由井號(hào)( # )包裹
在字符串字面量中放置擴(kuò)展分隔符來讓其中包含的特殊字符不生效
let str = "Line 1\nLine 2" //正常換行
let str2 = #"Line 1\nLine 2"# //Line 1\nLine 2 換行失效
如果字符串里有" # 需要顯示則首尾需要兩個(gè) ##
如果需要字符串中某個(gè)特殊符號(hào)的效果潦闲,使用匹配你包裹的井號(hào)數(shù)量的井號(hào)并在前面寫轉(zhuǎn)義符號(hào) \
let str3 = ##"Line 1\#nLine 2"\nLine 3\##nLine 4"##
/* 打印結(jié)果:
Line 1\#nLine 2"\nLine 3
Line 4
*/
可變與不可變字符串
字符串是值類型
- String 值在傳遞給方法或者函數(shù)的時(shí)候會(huì)被復(fù)制過去
- 賦值給常量或者變量的時(shí)候也是一樣
- Swift 編譯器優(yōu)化了字符串使用的資源,實(shí)際上拷貝只會(huì)在確實(shí)需要的時(shí)候才進(jìn)行
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 循環(huán)遍歷 String 中的每一個(gè)獨(dú)立的
- String 值可以通過傳入 Character 數(shù)組來構(gòu)造
let catCharacter: [Character] = ["C", "A", "T", "??"]
let catWord: String = String(catCharacter)
print(catWord)
字符串拼接
var str2 = "新年" + "快樂"
print(str2) //新年快樂
str2 += "迫皱!"
print(str2) // 新年快樂歉闰!
str2.append("??")
print(str2) // 新年快樂!??
字符串插值
- 字符串插值是一種從混合常量卓起、變量和敬、字面量和表達(dá)式的字符串字面量構(gòu)造新 String 值的方法
- 每一個(gè)你插入到字符串字面量的元素都要被一對(duì)圓括號(hào)()包裹,然后使用反斜杠\前綴
- 類似于 NSString 的 stringWithFormat 方法戏阅,但是更加簡(jiǎn)便昼弟,更強(qiáng)大
let age = 3
let desc = "\(age) 它的2.5倍是:\(Double(age) * 2.5)"
要在使用擴(kuò)展分隔符的字符串中使用字符串插值,在反斜杠后使用匹配首尾井號(hào)數(shù)量的井號(hào)
print(#"它的2.5倍是:\(Double(age) * 2.5)"#) // 它的2.5倍是:\(Double(age) * 2.5)
print(#"它的2.5倍是:\#(Double(age) * 2.5)"#) // 它的2.5倍是:7.5
字符串索引
- 每一個(gè) String 值都有相關(guān)的索引類型奕筐, String.Index舱痘,它相當(dāng)于每個(gè) 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
- 要訪問給定索引更遠(yuǎn)的索引离赫,你可以使用 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 屬性來訪問字符串中每個(gè)字符的索引
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)..<welcome.endIndex
welcome.removeSubrange(range)
print(welcome) // hello
子字符串
- 使用下標(biāo)或者類似 prefix(_:) 的方法得到的子字符串是 Substring 類型
- Substring 擁有 String 的大部分方法
- 子字符串重用一部分原字符串的內(nèi)存
var welcome = "hello, word!"
let subStr = welcome.prefix(5)
print(subStr)
let index = welcome.index(welcome.startIndex, offsetBy: 7)
let endStr = welcome[index..<welcome.endIndex]
print(endStr)
// Substring 可以轉(zhuǎn)成 String 類型
let newStr = String(endStr)
字符串比較
var welcome = "hello, word!"
var welcome1 = "hello"
print(welcome == welcome1) // false
print(welcome.hasPrefix("hello")) // true
print(welcome.hasSuffix("word!")) // true