// 教程地址:https://www.bilibili.com/video/BV1mT4y1C7JZ?p=16&vd_source=84310ee3c28453390868c23631486732
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
do {
// 數(shù)據(jù)類型轉(zhuǎn)換
// let i: Int = 10
// let j = 0.1
// let c = Int(j) + i
// print("c:\(c)")
//
// // 元組
// let error = (tit: 400, ddd: "not found")
// let d = error.0
// print("d:\(d)")
//
// let (code, des) = error
// print(code, des)
//
// let _ = error.tit
}
do {
// if語(yǔ)句
// var i = 10
// if i > 0 {
// print("i 大于 0")
// }
}
// 循環(huán) 還可以使用where條件
do {
// var i = 10
// repeat {
// print(10)
// } while i < 10
//
// for i in 0...3 {
// print(i)
// }
//
// for i in 0..<3 where i > 1 {
// print(i)
// }
//
// let array = [1, 2, 3 ,4]
// for item in array[0..<2] {
// print("haha\(item)")
// }
//
// for item in array[...2] {
// print(item)
// }
}
// switch
do {
var c = "c"
switch c {
case "1":
print("haha")
case "2", "3":
print("aaaa")
default:
break
}
// 區(qū)間匹配
var index = 10
switch index {
case 0...1:
fallthrough
case 2...3:
break
default:
break
}
// 元組匹配
let tuple = (1, 1)
switch tuple {
case (_, 1):
break
case (1...2, 1):
break
case (1...2, 1..<3):
break
default:
break
}
// 值綁定
switch tuple {
case (2, let a):
print(a)
case let (x, y):
print(x, y)
case let (a, b) where a > b: // 使用where過(guò)濾條件
print(a)
}
}
}
}
/// ------------
// 函數(shù)
func 函數(shù)() {
// 有入?yún)?有返回值
func func1(a: Int, b: Int) -> Int {
return a + b
}
// 無(wú)入?yún)o(wú)返回值
func fun2() {
}
// 帶參數(shù)標(biāo)簽和默認(rèn)參數(shù)值
func fun3(outname inname: Int = 10) {
}
// 可變參數(shù)
func fun4(numbers: Int..., age: Int) {
for index in numbers {
print(index)
}
}
// 輸入輸出參數(shù)
func fun5(a: inout Int) {
a += 5
}
}
/// ------------
func 別名typealias() {
// 給元組聲明一個(gè)別名
typealias Date = (year: Int, month: Int, day: Int)
func eatAt(date: Date) {
print(date.0)
print(date.year)
}
eatAt(date: (2011, 2, 1))
// 給函數(shù)聲明一個(gè)別名
typealias DeleteFunc = (Int, Int) -> Int
func operate(f: DeleteFunc, a: Int, b: Int) -> Int {
return f(a, b)
}
}
/// ------------
func 枚舉enum() {
// 原始值 rawValue
enum Score: Int {
case point = 2 // 設(shè)置原始值
case grade = 43 // 設(shè)置原始值
}
let s = Score.grade
// 打印原始值
print(s.rawValue)
let _ = Score(rawValue: 65)
// 隱式原始值,如果枚舉的原始值類型是Int或者String, swift會(huì)默認(rèn)設(shè)置原始值
enum Di: String {
case source // swift會(huì)默認(rèn)設(shè)置 case source = "source"
case north
}
typealias Location = (x: Int, y: Int)
// 關(guān)聯(lián)值
enum Direction {
case sourth(Location)
case east(Int)
case west(Float)
}
var dir = Direction.sourth((10, 20))
// 可以根據(jù)類型推斷出枚舉類型 就可以用.省略類型
dir = .east(1)
print(dir)
// 枚舉結(jié)合switc
switch dir {
case .east(let value) where (10...20).contains(value):
print(1)
case .sourth(let location) where location.x == 10:
print(location.x)
default:
break
}
}
/// ------------
func 可選項(xiàng)optional() {
// 類型后面+?
var name: String? = "jack"
name = nil
print(name) // Optional(jack)
// 可選值強(qiáng)制解包
let n = name!
print(n) // jack
// 可選綁定
if let number = Int("123123") {
// number是解包后的值 123123
} else {
}
// 可選綁定的if語(yǔ)句中 需要使用,分割
if let a = Int("1"),
let b = Int("2"),
a > b {
print("yes")
}
// 空合并運(yùn)算符 a??b , a為可選項(xiàng) b為可選項(xiàng)或者值都可以
var score1: String? = "11"
var score2: String? = "2"
print(score1 ?? score2)
print(score1 ?? 2) // 如果返回score1 那么會(huì)強(qiáng)制解包,因?yàn)楹竺娴氖且粋€(gè)值 非可選項(xiàng)
if let n = score1 ?? score2 {
// 這種寫(xiě)法等價(jià)于 scrol1 != nil || score2 != nil
}
if let n = score1,
let c = score2 {
// 這種寫(xiě)法等價(jià)于 scrol1 != nil && score2 != nil
}
// guard語(yǔ)句,當(dāng)條件為false的時(shí)候 會(huì)執(zhí)行括號(hào)里面的代碼
// guard 條件 else { return、break、continue退出}
guard let c = Int("adfasf") else {
print("條件沒(méi)有成立")
return
}
print(c)
// 隱式解包:如果一個(gè)可選值必定有值,可以在類型后面+!
let s: Int! = Int("123")
let d: Int = s
print(d)
// 多重可選項(xiàng)
let t: Int? = Int("234234")
let m: Int?? = t // 包裝了一個(gè)可選值的可選值
// 可選項(xiàng)本質(zhì)是枚舉
enum Optional<T> {
case same(T)
case none // nil
}
}
/// ------------
func 結(jié)構(gòu)體struct() {
// 編譯器會(huì)默認(rèn)給結(jié)構(gòu)體增加一個(gè)初始化器 Initializer, 它的宗旨是保證所有的存儲(chǔ)屬性都有初始值
struct Date {
var year: Int
var month: Int
var day: Int
}
let d1 = Date(year: 2022, month: 2, day: 2)
// 自定義初始化器
struct Datt {
var year: Int
var m: Int
// 自定義初始器,此時(shí)編譯器就不會(huì)生成默認(rèn)初始化器
init(yy: Int, mm: Int) {
self.m = mm
self.year = yy
}
}
// let類型的結(jié)構(gòu)體 它的存儲(chǔ)屬性也是let類型不可以修改
let d = Date(year: 11, month: 1, day: 1)
// d.day = 22 會(huì)報(bào)錯(cuò)
}
/// ------------
func 類class() {
// 編譯器不會(huì)給類生成默認(rèn)初始化器
class Student {
var age: Int
var name: String
init(age: Int, name: String) {
self.age = age
self.name = name
}
}
let s = Student(age: 1, name: "jack")
}
/// ------------
///
func 閉包() {
// swift中可以使用func來(lái)定義一個(gè)函數(shù),也可以使用閉包來(lái)定義函數(shù)
/*
閉包格式
{
(參數(shù)列表) -> 返回值類型 in
函數(shù)體代碼
}
*/
// 使用func定義函數(shù)
func sum(a: Int, b: Int) -> Int {
a + b
}
// 使用閉包定義函數(shù)
var fuck = {
(a: Int, b: Int) -> Int in
a + b
}
let _ = sum(a: 1, b: 2) // 調(diào)用func函數(shù)
let _ = fuck(2, 4) // 調(diào)用閉包,閉包會(huì)省略參數(shù)標(biāo)簽
// 如果閉包是函數(shù)的最后一個(gè)參數(shù) 可以使用尾隨閉包
func delete(a: Int, b: Int, fc: (Int ,Int) -> Int) -> Int {
fc(a, b)
}
_ = delete(a: 1, b: 2) { a, b in
a + b
}
_ = delete(a: 1, b: 3, fc: {
$0 + $1
})
}
/// ------------
func 方法() {
// 值類型如果想要在方法中修改屬性 需要使用mutating關(guān)鍵字
struct DDD {
var x: Int = 10
mutating func changeX(a: Int) {
x = a
}
}
class DS {
// 相當(dāng)于dispatch once
static let a = "adfaf"
}
// 消除函數(shù)返回值未使用的警告@discardableResult
@discardableResult func delete(a: Int, b: Int) -> Int {
a - b
}
// 下標(biāo)subscript
class Person {
var age: Int = 10
// 下標(biāo)方法可以是類方法 在前面增加static字段即可
subscript(index: Int) -> Int {
set {
if index == 0 {
age = newValue
}
}
get {
if index == 0 {
return age
}
return 3
}
}
}
}
/// ------------
func 繼承() {
// 類可以繼承,結(jié)構(gòu)體不行
// 繼承后可以重寫(xiě)父類的方法或者屬性 使用override關(guān)鍵字
class Animal {
var name = ""
var age:Int = 10
}
class Dog: Animal {
// 重寫(xiě)父類屬性為計(jì)算屬性
override var name: String {
set {
super.name = newValue
}
get {
return ""
}
}
// 在子類中給父類存儲(chǔ)屬性添加觀察器, 也可以給父類的計(jì)算屬性添加屬性觀察器
override var age: Int {
willSet {
print(newValue)
}
didSet {
print(oldValue)
}
}
// 被final修飾的屬性 方法,禁止被重寫(xiě)。類禁止被繼承
}
}
/// ------------
func 初始化構(gòu)造鏈() {
// 父類的屬性在自己的初始化方法中給屬性賦值,不會(huì)觸發(fā)屬性觀察器
// 父類的屬性 在子類的初始化方法中給屬性賦值,會(huì)觸發(fā)屬性觀察器
class Animal {
var age: Int
init(age: Int) {
self.age = age
}
}
class Dog: Animal {
var name: String
init(name: String) {
// 1. 子類先初始化自己的東西
self.name = name
// 2. 再調(diào)用父類構(gòu)造方法
super.init(age: 1)
// 第二階段后 才可以使用self關(guān)鍵字
// 3. 最后可以自定義一些東西
age = 10
}
}
// --------
class Person {
var age: Int
// 使用關(guān)鍵字required 那么子類必須繼承或者重寫(xiě)該指定初始化器
required init(age: Int) {
self.age = age
}
}
class XiaoMing: Person {
// 子類也必須使用required關(guān)鍵詞重寫(xiě) 不用加override
required init(age: Int) {
super.init(age: age)
}
}
// -----
// 可失敗初始化器
class Bird {
var age: Int
init?(age: Int) {
if age < 0 {
return nil
}
self.age = age
}
}
// ------
// 反初始化器
class Fish {
// 先調(diào)用子類的deinit方法,后再調(diào)用父類的deinit方法
// 父類的反初始化方法可以繼承給子類,即子類銷毀的時(shí)候 會(huì)調(diào)用父類的deinit方法
deinit {
print("銷毀了")
}
}
}
func 可選鏈() {
class Person {
var age: Int = 0
}
var p: Person? = Person()
// 結(jié)果是可選項(xiàng) 因?yàn)閜有可能是nil,如果p是nil的情況 那么就不會(huì)繼續(xù)調(diào)用.age方法
let _ = p?.age
// 如果本來(lái)就是可選項(xiàng) 那么可選鏈不會(huì)再次包裝 也就是不會(huì)出現(xiàn)??的情況
// ----
// 利用可選鏈有值才會(huì)繼續(xù)向后執(zhí)行的特性
// 第二行加上? 會(huì)判斷 如果w有值才會(huì)繼續(xù)賦值20, 如果w沒(méi)有值 那么就不會(huì)執(zhí)行后面的賦值操作了
var w: Int? = 10
w? = 20
}
/// ------------
// 協(xié)議
protocol 協(xié)議 {
func haha() // 定義方法
var name: String { get set } // 定義屬性 并聲明可讀可寫(xiě)權(quán)限, 子類可以實(shí)現(xiàn)一個(gè)存儲(chǔ)屬性 也可以是計(jì)算屬性
var age: String { get }
subscript(index: Int) -> String { get set }
// 定義類方法 必須用static關(guān)鍵字 不能使用class,因?yàn)橛锌赡苁墙Y(jié)構(gòu)體遵守這個(gè)協(xié)議
static func eat()
mutating func say() // 如果要在方法中修改屬性值,必須在協(xié)議中增加mutating關(guān)鍵字
// 協(xié)議中定義方法不能帶默認(rèn)參數(shù)值
// 協(xié)議中定義屬性必須用var 不能用let,因?yàn)閷?shí)現(xiàn)的時(shí)候 有可能是計(jì)算屬性 值是不確定的
// 協(xié)議中聲明的權(quán)限 實(shí)現(xiàn)的時(shí)候可以大于 不能小于,比如是get只讀權(quán)限 實(shí)現(xiàn)的時(shí)候 可以為可讀可寫(xiě)
// 協(xié)議中還可以定義默認(rèn)初始化方法。但是實(shí)現(xiàn)類必須加上required關(guān)鍵字
init(age: Int)
}
protocol hha {
}
class PPPPP {
}
// 別名
typealias 多組合 = PPPPP & 協(xié)議 & hha
// 協(xié)議組合,要求參數(shù)是指定類型且遵守必要的協(xié)議
func eat(a: 多組合) {
}
/// ----------
/// 枚舉遵循CaseIterable協(xié)議 就可以實(shí)現(xiàn)枚舉遍歷
enum Season: CaseIterable {
case summer
case winter
}
func 遍歷season() {
for cacse in Season.allCases {
print(cacse)
}
}
/// ----------
/// 對(duì)象遵守CustomStringConvertible并實(shí)現(xiàn)description方法 就可以自定義print內(nèi)容
class CustomStringC: CustomStringConvertible {
var age: Int = 0
var description: String {
return "\(age)哈哈"
}
}
/// --------------
/// swift提供了兩種特殊的類型 Any和AnyObject?;蛘哒f(shuō)是兩種協(xié)議
/// Any可以代表任意類型 枚舉、結(jié)構(gòu)體、類型、函數(shù)
/// AnyObject可以代表任意類類型,不能代表結(jié)構(gòu)體。 如果協(xié)議后面注明AnyObject,表示只有類才能遵守這個(gè)協(xié)議
protocol ClassProtocol: AnyObject {
}
class BBB: ClassProtocol {
}
var anyArr = Array<Any>() // 存放任意類型的數(shù)組
var anyObjArr = Array<AnyObject>() // 存放任意類的數(shù)組
var anyDic = [Any]()
var anyObjDic = [AnyObject]()
/// --------------
/// is as as? as!
/// is用來(lái)判斷是否是某種類型
/// as用來(lái)做類型轉(zhuǎn)換。 as?表示可選轉(zhuǎn)換, as!表示強(qiáng)制解包, as表示百分百轉(zhuǎn)換成功 比如as Any時(shí)候可以用as
///
func is_as() {
var a: Any
a = 10
if a is Int {
print("是整型")
}
class Person {
func eat() {
print("eat")
}
}
var p: Any = Person()
// as?拿到的是可選類型 因?yàn)檗D(zhuǎn)換有可能失敗
// 第二個(gè)?代表是可選鏈調(diào)用eat方法,當(dāng)前面成立 不為nil 才會(huì)調(diào)用eat方法
(p as? Person)?.eat()
}
/// --------------
protocol haha {
func test() -> Self
}
func self_type_AnyClass() {
// X是類
// X.self是一個(gè)元類型的指針,元類型中存放著類的相關(guān)信息,可以稱為元類型 相當(dāng)于oc的class
// X.self是X.type類型
class Person {
required init() {
}
}
var typet: Person.Type = Person.self
// oc中使用class來(lái)創(chuàng)建vc ,在swift中可以使用元類型x.type來(lái)創(chuàng)建
// [[class alloc] init];
let _ = Person.self.init()
func create(type: Person.Type) {
let _ = type.init()
}
// Self一般用作返回值類型 或者參數(shù)類型,限定返回值必須跟方法調(diào)用者是同一個(gè)類型
// 類似于oc的instancetype
class Person1: haha {
required init() {
}
func test() -> Self {
return type(of: self).init()
}
}
}
func 錯(cuò)誤error() {
// swift可以自定義運(yùn)行時(shí)錯(cuò)誤
// 可以自定義類 遵守Error協(xié)議, 可以是枚舉或者類或者結(jié)構(gòu)體
enum MyError: Error {
case local(String)
case remote(Int)
}
// 方法需要增加throws關(guān)鍵字
// 方法內(nèi)部拋出錯(cuò)誤使用throw關(guān)鍵字
func delete(a: Int, b: Int) throws -> Int {
if a < b {
throw MyError.local("haha")
}
return a - b
}
// 調(diào)用的時(shí)候 可以使用try try? try!
// 1,調(diào)用時(shí)候一般使用do catch來(lái)捕捉錯(cuò)誤
do {
print(1)
var _ = try delete(a: 10, b: 1) // 如果這一步異常了 就不會(huì)執(zhí)行下面print2
print(2)
} catch let MyError.local(ll) {
print(ll)
} catch let MyError.remote(rrr) {
print(rrr)
} catch {
print("兜底")
}
// 語(yǔ)法糖
do {
try delete(a: 10, b: 1)
} catch let error as MyError {
print(1)
} catch is MyError {
print(23)
} catch {
}
// 2. 調(diào)用方法的時(shí)候 還可以不處理 使用throws繼續(xù)往上拋
func callDelete() throws {
var _ = try delete(a: 10, b: 1) // 如果這一行執(zhí)行報(bào)錯(cuò) 后面print也不會(huì)再執(zhí)行了
print(3)
}
// 3.使用try? try!
var _ = try? delete(a: 10, b: 10) // 返回的是Int?類型 如果正常是可選值Optional(Int) 如果錯(cuò)誤是nil ,跟下面的寫(xiě)法等價(jià)
do {
try delete(a: 10, b: 10)
} catch {
}
// 還可以使用try! 強(qiáng)制解包
let _ = try! delete(a: 10, b: 10) // 返回值是Int類型
}
func 懶執(zhí)行defer() {
// 用來(lái)定義任何方式離開(kāi)前 都必須會(huì)執(zhí)行的代碼,包括return 拋異常error
defer {
}
}
func 泛型() {
// 1.方法中使用泛型
// 交換參數(shù)
func swapValue<T>(a: inout T, b: inout T) {
(a, b) = (b , a)
}
var a = 10
var b = 2
swapValue(a: &a, b: &b)
// 把泛型函數(shù)賦值給變量
let fu: (inout Int, inout Int) -> () = swapValue
fu(&a, &b)
// 2.類中使用泛型
class Stack<T> {
var array = [T]()
func push(t: T) {
array.append(t)
}
}
// 創(chuàng)建類的時(shí)候 需要顯式標(biāo)明類型
var s = Stack<Int>()
// 如果是子類繼承 也需要增加泛型
class SSStack<T>: Stack<T> {
}
}
/// ------
func associatedType關(guān)聯(lián)類型() {
}
// 給協(xié)議中用到的類型 定義一個(gè)占位名稱,可以簡(jiǎn)單理解協(xié)議中想要實(shí)現(xiàn)泛型 不能用上面的<T>這種方式 只能使用關(guān)聯(lián)類型這種方式
// 協(xié)議中可以定義多個(gè)類型
protocol Stack {
associatedtype element
mutating func push(e: element)
}
// 遵守協(xié)議的時(shí)候, 可以通過(guò)typealias來(lái)指定類型,也可以省略typealias 讓編譯器自己根據(jù)我們寫(xiě)的方法類型判斷
class BBBB: Stack {
typealias element = Int
func push(e: Int) {
print(1)
}
}
/// -------- 類型約束
/// 約束泛型t的類型或者必須遵守協(xié)議
func mutal<T: PPPPP & Stack>(a: T) -> T {
return a
}
/// 約束協(xié)議中的泛型必須遵守協(xié)議
protocol Hadaf {
associatedtype T: Stack
}
// 還可以在func中增加where語(yǔ)句做更細(xì)致的類型約束
func aasdfas<T, M>(a: T, b: M) where T == M {
}
/// some 限制只能返回一種類型,不透明協(xié)議
protocol Masdfasf {
associatedtype T
}
class Flya: Masdfasf {
typealias T = Int
}
class FlaB: Masdfasf {
typealias T = Double
}
func getf(a: Int) -> some Masdfasf { // 限制方法內(nèi)部 只能返回一種遵守Masdfasf的類型 不能返回兩種
return FlaB()
}
///-------- 溢出運(yùn)算符
/// swift支持溢出運(yùn)算 &+ &- &*
var max = Int8.max
var mmm = max + 1 // 會(huì)崩潰 因?yàn)橐绯隽?var mmmm = max &+ 1 // 不會(huì)崩潰 但是會(huì)變成最小值 因?yàn)橐绯隽?
///-------- 運(yùn)算符重載
struct HhhAAA {
// 運(yùn)算符重載方法 需要增加static關(guān)鍵字
static func +(a: HhhAAA, b: HhhAAA) -> HhhAAA {
return a
}
static func +=(a: HhhAAA, b: HhhAAA) -> HhhAAA {
return a
}
}
/// equatable協(xié)議 就是重載==運(yùn)算符
class Eafafd: Equatable {
var name: Int = 0
static func ==(lhs: Eafafd, rhs: Eafafd) -> Bool {
return lhs.name == rhs.name
}
}
/// Comparable協(xié)議 用來(lái)重載<實(shí)現(xiàn)比較大小
//class ASDFAFD: Comparable {
// static func < (lhs: ASDFAFD, rhs: ASDFAFD) -> Bool {
// return true
// }
//
//}
/// 自定義運(yùn)算符 使用operator關(guān)鍵字
///
/// ------------ 拓展 entension,類似于oc的分類
/// 可以添加方法、計(jì)算屬性、下標(biāo)、(便捷)初始化器、嵌套類型、協(xié)議等等
//擴(kuò)展不能辦到的事情:
// 口不能覆蓋原有的功能
// 口不能添加存儲(chǔ)屬性,不能向已有的屬性添加屬性觀察器
// 口不能添加父類
// 口不能添加指定初始化器,不能添加反初始化器
class Paer {
}
extension Paer {
}
/// ------------ 訪問(wèn)控制 權(quán)限控制
/// 訪問(wèn)權(quán)限控制這塊,Swift提供了5個(gè)不同的訪問(wèn)級(jí)別(以下是從高到低排列,實(shí)體指被訪問(wèn)級(jí)別修飾的內(nèi)容)
/// 模塊可以理解為一個(gè)可執(zhí)行文件 target,一個(gè)動(dòng)態(tài)庫(kù)或者靜態(tài)庫(kù)是一個(gè)模塊
//口open:允許在定義實(shí)體的模塊、其他模塊中訪問(wèn),允許其他模塊進(jìn)行繼承、重寫(xiě)(open只能用在類、類成員上)
//口public:允許在定義實(shí)體的模塊、其他模塊中訪問(wèn),不允許其他模塊進(jìn)行繼承、重寫(xiě)
//口internal:只允許在定義實(shí)體的模塊中訪問(wèn),不允許在其他模塊中訪問(wèn)
//口fileprivate:只允許在定義實(shí)體的源文件中訪問(wèn)
//口private:只允許在定義實(shí)體的封閉聲明中訪問(wèn)
//訪問(wèn)級(jí)別的使用準(zhǔn)則
//一個(gè)實(shí)體不可以被更低訪問(wèn)級(jí)別的實(shí)體定義,比如
//變量\常量類型 >= 變量\常量
//口參數(shù)類型、返回值類型 >= 函數(shù)
//父類子類 >= 父協(xié)議子協(xié)議
//原類型 >= typealias
//原始值類型、關(guān)聯(lián)值類型 >= 枚舉類型
//定義類型A時(shí)用到的其他類型 >= 類型A
/// ----- 內(nèi)存管理 weak unowned
/// weak定義的必須是可選類型的var 因?yàn)殇N毀后arc會(huì)自動(dòng)把該弱引用置為nil 類似于oc的weak
/// unowned 類似于oc的assing 對(duì)象銷毀后還保存著該指針 再次訪問(wèn)容易引發(fā)野指針崩潰
// 如果想在定義閉包屬性的同時(shí)引用self,這個(gè)閉包必須是lazy的(因?yàn)樵趯?shí)例初始化完畢之后才能引用self)
func weakUnowned() {
class Person {
//左邊的閉包fn內(nèi)部如果用到了實(shí)例成員(屬性、方法)
lazy var fn: (() ->()) = {
[weak self] in
//口編譯器會(huì)強(qiáng)制要求明確寫(xiě)出self
self?.run()
}
func run() { print("run") }
deinit { print("deinit") }
}
//如果lazy屬性是閉包調(diào)用的結(jié)果,那么不用考慮循環(huán)引用的問(wèn)題(因?yàn)殚]包調(diào)用后,閉包的生命周期就結(jié)束了)
class Person1 {
var age: Int = 0
lazy var getAge: Int = {
self.age
}()
}
}
///---------- 逃逸閉包escaping
///逃逸閉包、逃逸閉包,一般都是當(dāng)做參數(shù)傳遞給函數(shù)
///非逃逸閉包:閉包調(diào)用發(fā)生在函數(shù)結(jié)束前,閉包調(diào)用在函數(shù)作用域內(nèi)
///逃逸閉包:閉包有可能在函數(shù)結(jié)束后調(diào)用,閉包調(diào)用逃離了函數(shù)的作用域,需要通過(guò)@escaping聲明
///
func 逃逸閉包escaping() {
typealias Fn = () -> ()
//fn是非逃逸閉包
func test1(_ fn: Fn) { fn() }
//fn是逃逸閉包
var gFn: Fn?
func test2(_ fn: @escaping Fn) { gFn = fn }
}
///---------- 局部作用域 do, 類似于oc的{ }
func 局部作用域do() {
do {
var a = 10
}
do {
var a = 2
}
}
/// ------ 指針
func pointer() {
func unsafePointer(a: UnsafePointer<Int>) {
print(a.pointee)
}
func unsafeMPointer(a: UnsafeMutablePointer<Int>) {
a.pointee = 20
}
var b = 10
unsafePointer(a: &b)
unsafeMPointer(a: &b)
// Swift中也有專門(mén)的指針類型,這些都被定性為“Unsafe”(不安全的),常見(jiàn)的有以下4種類型:
// UnsafePointer<Pointee>似 const Pointee *, 不可修改 只能訪問(wèn)
// UnsafeMutablePointer<Pointee>似 Pointee * ,可以修改指針指向的內(nèi)容
// UnsafeRawPointer似 const void *
// UnsafeMutableRawPointer 類似 void *
}
/// ---- 通配符
/// _ 匹配任何值
/// _? 匹配非nil值 針對(duì)可選項(xiàng)來(lái)說(shuō)
///
func 通配符() {
enum Price {
case a(Int, Int?)
case b(Double?)
}
var c = Price.a(10, 10)
switch c {
case .a(let first, _): // 第二個(gè)值nil或者有值都可以
print(first)
case .b(_?): // 匹配非空
print("afa")
default:
break
}
}
/// ---- 枚舉case模式
///
func enumcase() {
var age = 10
// if case等價(jià)于只有一個(gè)case的switch語(yǔ)句
if case 0...9 = age {
print("haha")
}
switch age {
case 0...9:
print("haha")
default: break
}
// guard case模式
guard case 0..<10 = age else {
return
}
}
/// ------ 注釋
func 注釋() {
// FIXME: ADF
// TODO: HAHD
// MARK: ASDFAF
// MARK: - ADFASF
}
/// --- oc調(diào)用swift
func oc調(diào)用swift() {
@objc(NewClass) // 可以使用@objc自定義方法名和類名
@objcMembers class Caaa: NSObject { // 需要繼承自NSObject
// @objcMembers可以把所有方法和屬性都暴露給oc 相當(dāng)于每個(gè)成員前面都增加@objc
@objc func callrun() {
perform(#selector(run))
perform(#selector(run(a:)))
}
@objc func run(a: Int) {
}
}
}
/// --- string substring 字符串處理
func stringt() {
// String可以通過(guò)下標(biāo)、prefix、 suffix等截取子串,子串類型不是String,而是Substring
var str = "1_2_3_4_5"
//1_2
var substr1 = str.prefix(3)
var substr2 = str.suffix(3)
var range = str.startIndex..<str.index(str.startIndex, offsetBy: 3)
var substr3 = str[range]
//最初的String,1_2_3_4_5
print(substr3.base)
// Substring -> String
var str2 = String(substr3)
}
/// ------ swift 支持kvc kvo
/// 類需要繼承自nsobject
/// 用@objc dynamic來(lái)修飾屬性
///
///
///
/// ------ swift 關(guān)聯(lián)對(duì)象 給拓展增加存儲(chǔ)屬性
class Prer {
}
extension Prer {
private static var nameKey = true // 使用void?也行 因?yàn)槎颊加靡粋€(gè)字節(jié)
var name: Int {
get {
objc_getAssociatedObject(self, &Self.nameKey) as! Int
}
set {
objc_setAssociatedObject(self, &Prer.nameKey, newValue, .OBJC_ASSOCIATION_ASSIGN)
}
}
}
/// ------ 可選項(xiàng)的map和flatMap
/// map和flatMap會(huì)先判斷 如果是非nil才會(huì)繼續(xù)執(zhí)行,flatMap區(qū)別是會(huì)判斷已經(jīng)是可選項(xiàng)了 就不會(huì)再次包裝 即不會(huì)出現(xiàn)??的情況
func optionalMap() {
var age: Int? = 10
var b = age.flatMap {
$0 + 1
}
print(b as Any)
}