簡單記錄一些自己容易忘記的碎片化的點
一、tips
1、swift中文名雨燕
2、不用編寫main函數,將全局范圍內首句可執行代碼作為程序入口
3、一句代碼尾部可以省略分號,多句代碼寫到同一行必須用分號隔開
4、var定義變量,let定義常量,編譯器能夠自動推斷出變量和常量的類型
二、常見數據類型
三、函數文檔注釋
///
/// 求和【概述】
///
/// 將兩個整數相加【更加詳細的描述】
///
/// - Parameter a: 參數a描述
/// - Parameter b: 參數b描述
/// - Returns :兩個整數的和
///
/// - Note:傳入兩個整數即可【批注】
///
func sum(a: Int, b: Int) -> Int {
a + b
}
調用的時候,按住option,點擊函數名即可出現下圖的注釋效果:
MARK / TODO / FIXME
- MARK: 類似于OC中的 #pragma mark
- MARK: - 類似于OC中的 #pragma mark - (預覽的時候跟上個相同級別的標注之間會有線隔開,見下面圖片中灰色線條)
- TODO: 用于標記未完成的任務
- FIXME: 用于標記待修復的問題
-
warning("undo"):如果覺得 TODO: 不夠明顯, 可以考慮用這個
// MARK: - 私有方法
// MARK: test1方法
private func test1() {
// TODO: 未完成
}
// MARK: test2方法
private func test2() {
// FIXME: 有待修復的問題
}
// MARK: - 公共方法
// MARK: test3方法
public func test3() {}
// MARK: test4方法
public func test4() {}
// 警告,會在代碼中有明顯的黃色嘆號提示
#warning("undo")
四、參數
1、可以修改參數標簽
func gotoSchool(at time: String) {
print("go to school \(time)")
}
gotoSchool(at: "08:00")
2、可以使用下劃線_ 省略參數標簽,相對復雜的盡量不要省略
func sum(_ a: Int, _ b: Int) -> Int {
a + b
}
print(sum(10, 20))
3、參數類型后面加上三個點表示可變參數,可以傳多個對應類型的參數
需要注意的問題:
1、一個函數最多只能有一個可變參數
2、緊跟在可變參數后面的參數不能省略參數標簽
func sum(_ numbers: Int...) -> Int {
var total = 0
for number in numbers {
total += number
}
return total
}
print(sum(10, 20, 30, 40)) // 100
五、Optional-可選項
可選項,一般也叫可選類型,它允許將值設置為nil,在類型名稱后面加個?來定義一個可選項
var name: String? = "Jack"http:// 不寫= "Jack",默認就是nil
name = nil
可選項是對其它類型的一層包裝,如果要從可選項中取出被包裝的數據,需要使用感嘆號!進行強制解包
let count: Int? = 10
var countAdd: Int = count!
countAdd += 10
print(countAdd)
如果對值為nil的可選項進行強制解包,會產生運行時錯誤,程序直接崩潰
let count: Int?
// 如果count為nil,強制解包程序會crash
count!
// 在實際開發中我們一般會這樣做
if let temp = count {
// 在這里進行處理
print(temp)
}
可選項的本質是 enum 類型,下面兩種寫法完全等價
let a: Int? = 10
let b: Optional<Int> = .some(10)
六、運算符
1、??:合并空值運算符
a ?? b
(1)用于判斷常量或者變量的值是否為nil,如果為nil,則取后面的值,不為nil,取前面的值。有點兒類似三目運算符
(2)上面的表達式,如果a有值,則取a,如果a為nil,則取b
應用示例:
func sum(a: Int?, b: Int?) -> Int {
// 方法一:如果a或者b有nil,則程序會crash
return a! + b!
//方法二:判斷條件太多,容易遺漏
if a != nil {
if b != nil {
return a! + b!
} else {
return a!
}
} else {
if b != nil {
return b!
} else {
return 0
}
}
//方法三:簡潔、安全
return (a ?? 0) + (b ?? 0)
}
2、reversed():倒序索引
for i in (0...9).reversed() {
print(i)
}
// 輸出結果
9
8
7
6
5
4
3
2
1
0
3、 (逗號)
做判斷的時候在兩個條件中間加一個
相當于 &&
let a: Int = 11
// 判斷1 和 判斷2 等價
// 判斷1
if a > 0, a > 11 {
print(123)
}
// 判斷2
if a > 0 && a > 11 {
print(123)
}
七、guard
guard語句,有點兒類似if語句,但是后面會一直跟著else語句,并且else里面的語句只有在guard條件不為真的時候才執行。下面兩段代碼是檢測ip地址是否正確,第一段用if實現,第二段用guard實現。
// 試用if判斷ip地址是否正確
func checkIpAddress(ipAddress: String) -> (Int, String) {
// 用點來分割ip地址
let compoment = ipAddress.split(separator: ".")
if compoment.count == 4 {
if let first = Int(compoment[0]), first >= 0 && first < 256 {
if let second = Int(compoment[1]), second >= 0 && second < 256 {
if let third = Int(compoment[2]), third >= 0 && third < 256 {
if let fourth = Int(compoment[3]), fourth >= 0 && fourth < 256 {
return (100, "ip地址是正確的")
} else {
return (4, "ip地址第四部分不對")
}
} else {
return (3, "ip地址第三部分不對")
}
} else {
return (2, "ip地址第二部分不對")
}
} else {
return (1, "ip地址第一部分不對")
}
} else {
return (0, "ip地址必須有四部分")
}
}
// 試用guard判斷ip地址是否正確
func checkIpAddress(ipAddress: String) -> (Int, String) {
let compoment = ipAddress.split(separator: ".")
guard compoment.count == 4 else {
return (0, "ip地址必須有四部分")
}
guard let first = Int(compoment[0]), first >= 0 && first < 256 else {
return (1, "ip地址第一部分不對")
}
guard let second = Int(compoment[1]), second >= 0 && second < 256 else {
return (2, "ip地址第二部分不對")
}
guard let third = Int(compoment[2]), third >= 0 && third < 256 else {
return (3, "ip地址第三部分不對")
}
guard let fourth = Int(compoment[3]), fourth >= 0 && fourth < 256 else {
return (4, "ip地址第四部分不對")
}
return (100, "ip地址是正確的")
}
八、字符串
1、首字母大寫:capitalized
let str = "hello world"
print(str.capitalized)
// 輸出:Hello World
2、字符全部轉大寫
let str = "hello world"
print(str.uppercased())
// 輸出:HELLO WORLD
3、字符全部轉小寫
let str = "HeLLo WoRlD"
print(str.lowercased())
// 輸出:hello world
九、數組
1、以逗號拼接字符串數組所有元素為一個字符串
let arr = ["you", "only", "live", "once"]
let newArr = arr.joined(separator: ",")
print(newArr)
// 輸出
you,only,live,once
2、字符串轉數組
let str = "you only live once"
let arr = str.components(separatedBy: " ")
print(arr)
// 輸出
["you", "only", "live", "once"]
十、輸入輸出參數(In-Out Parameter)
可以用inout定義一個輸入輸出參數,在函數內部修改外部變量的值
inout的本質是地址傳遞(引用傳遞)
inout參數不能有默認值
可變參數不能標記為inout
inout參數的傳入值能被多次賦值
func swapValue(_ v1: inout Int, _ v2: inout Int) {
let tmp = v1
v1 = v2
v2 = tmp
}
var num1 = 10
var num2 = 20
swapValue(&num1, &num2)
print(num1, num2)
// 打印結果
// 20 10
十一、可變參數
參數類型后面加三個點表示可變參數
一個函數最多只能有1個可變參數
緊跟在可變參數后面的參數不能省略參數標簽
func sum(_ numbers: Int..., other: Int) -> Int {
var total = 0
for item in numbers {
total += item
}
return total + other
}
let result = sum(1, 2, 3, 4, other: 5)
print(result)
// 打印結果
// 15
十二、屬性
嚴格來說,屬性可以按下面方式劃分
實例屬性(Instance Property)
1.存儲實例屬性(Stored Instance Property)存儲在實例的內存中,每個實例都有1份
2.計算實例屬性(Computed Instance Property)類型屬性(Type Property)
1.存儲類型屬性(Stored Type Property)整個程序運行過程中,就只有1份內存(類似于全局變量)
2.計算類型屬性(Computed Type Property)
十三、mutating
結構體和枚舉是值類型,默認情況下,值類型的屬性不能被自身的實例方法修改
在 func 關鍵字前加 mutating 可以允許這種修改行為
// 結構體
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(_ deltaX: Double, _ deltaY: Double) {
x += deltaX
y += deltaY
}
}
// 枚舉
enum StateSwitch {
case low, middle, high
mutating func next() {
switch self {
case .low:
self = .middle
case .middle:
self = .high
case .high:
self = .low
}
}
}
十四、@discardableResult
調用有返回值的方法,如果沒有使用返回的值,會有一個黃色的警告,如果想消除這個警告,可以在方法前面加上 @discardableResult
注:除非特殊需求,建議非必要不要使用
@discardableResult func add(_ a: Int, _ b: Int) -> Int {
a + b
}
// 這樣直接調用就不會有警告了
add(10, 3)
十五、class & static & final
1、被class修飾的類型方法、下標,允許被子類重寫
被static修飾的類型方法、下標,不允許被子類重寫
2、被class修飾的計算類型屬性,可以被子類重寫
被static修飾的類型屬性(存儲、計算),不可以被子類重寫
3、被 final 修飾的方法、下標、屬性,禁止被重寫
被final修飾的類,禁止被繼承
十六、(+) (-)
Swift 編譯器特性
// 兩個 Int 類型參數相加、相減
let dic: [String: (Int, Int) -> Int] = [
"sum": (+),
"minus": (-)
]
let result1 = dic["sum"]?(10, 5)
let result2 = dic["minus"]?(12, 5)
print(result1)
print(result2)
十七、Any / AnyObject
- Any:可以代表任意類型(枚舉、結構體、類、也包括函數類型)
- AnyObject:可以代表任意 類 類型(在協議后面加上:AnyObject,代表只有類能遵守和這個協議)
十八、數組、字典聲明
// 下面兩種聲明數組的方法完全等價
var arr = Array<Int>()
var arr = [Int]()
// 下面兩種聲明字典的方法完全等價
var dic = Dictionary<Int, Int>()
var dic = [Int: Int]()
十九、is、as、as?、 as!
i s 用來判斷是否為某種類型, as用來做類型強制轉換
二十、訪問控制(Access Control)
在訪問權限控制這塊,Swift提供了5個不同的訪問級別,以下是從高到低排列,實體指的是被訪問級別修飾的內容
- open:允許在定義實體的模塊,其它模塊中訪問,允許其它模塊進行繼承、重寫(open只能用在類、類成員上)
- public:允許在定義實體的模塊、其它模塊中訪問、不允許其它模塊進行繼承、重寫
- internal:只允許在定義實體的模塊中訪問,不允許在其它模塊中訪問
- fileprivate:只允許在定義實體的源文件中訪問
- private:只允許在定義實體的封閉聲明中訪問
注:絕大部分實體默認都是 internal 級別
二十一、API可用性說明
比如你自己封裝了一個三方框架,但是在升級過程中有的API被廢棄掉,或者已過期,可以進行下面的操作
struct Student {
// 方法名重命名
@available(*, unavailable, renamed: "study")
func study1() {}
func study() {}
// 方法在iOS被廢棄掉
@available(iOS, deprecated: 11)
func run() {}
}
let stu = Student()
// 會提示 'run()' was deprecated in iOS 11
stu.run()
// 會提示 'study1()' has been renamed to 'study'
stu.study1()