swift 小知識點匯總

1. class 和 struct 的區(qū)別

class 為類, struct 為結(jié)構(gòu)體, 類是引用類型, 結(jié)構(gòu)體為值類型, 結(jié)構(gòu)體不可以繼承

2.map、filter、reduce 的作用

map 用于映射, 可以將一個列表轉(zhuǎn)換為另一個列表

[1, 2, 3].map{"\($0)"}// 數(shù)字數(shù)組轉(zhuǎn)換為字符串數(shù)組
//["1", "2", "3"]

filter 用于過濾, 可以篩選出想要的元素

[1, 2, 3].filter{$0 % 2 == 0} // 篩選偶數(shù)
//[2]

reduce 合并

[1, 2, 3].reduce(""){$0 + "\($1)"}// 轉(zhuǎn)換為字符串并拼接
//"123"

3.map 與 flatmap 的區(qū)別

flatmap 有兩個實現(xiàn)函數(shù)實現(xiàn)

    public func flatMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult] 

這個方法, 中間的函數(shù)返回值為一個可選值, 而 flatmap 會丟掉那些返回值為 nil 的值
例如

//例如
["1", "@", "2", "3", "a"].flatMap{Int($0)}
// [1, 2, 3]
["1", "@", "2", "3", "a"].map{Int($0) ?? -1}
//[Optional(1), nil, Optional(2), Optional(3), nil]

另一個實現(xiàn)
public func flatMap<SegmentOfResult>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Iterator.Element] where SegmentOfResult : Sequence
中間的函數(shù), 返回值為一個數(shù)組, 而這個 flapmap 返回的對象則是一個與自己元素類型相同的數(shù)組

func someFunc(_ array:[Int]) -> [Int] {
    return array
}
[[1], [2, 3], [4, 5, 6]].map(someFunc)
//[[1], [2, 3], [4, 5, 6]]
[[1], [2, 3], [4, 5, 6]].flatMap(someFunc)
//[1, 2, 3, 4, 5, 6]

其實這個實現(xiàn), 相當于是在使用 map 之后, 再將各個數(shù)組拼起來一樣的

[[1], [2, 3], [4, 5, 6]].map(someFunc).reduce([Int]()) {$0 + $1}
// [1, 2, 3, 4, 5, 6]

4.如何獲取當前代碼的函數(shù)名和行號

file 用于獲取當前文件文件名

line 用于獲取當前行號

column 用于獲取當前列編號

function 用于獲取當前函數(shù)名

var file: String = #file
var line: String = #line
var column: String = #column
var function: String = #function
method: String = #function,
print("\(file)--\(line)--\(columne)--\(function))

5.private,fileprivate,internal,public 和 open 五種訪問控制的權(quán)限

//1.當private 或fileprivate 修飾屬性的時候
privte 修飾的屬性只能在本類的作用域且在當前文件內(nèi)能訪問
fileprivate 修飾的屬性只能在當前文件內(nèi)訪問到,不管是否在本類作用域

//2. fileprivate 修飾方法的時候
fileprivate 修飾的方法,類的外部無法調(diào)用
fileprivate 修飾方法,子類定義的同一個文件中,可以訪問
fileprivate 修飾方法,子類定義不在同一個文件,不可以訪問


//3.public 和 open 的區(qū)別
這兩個都用于在模塊中聲明需要對外界暴露的函數(shù), 區(qū)別在于, public 修飾的類, 在模塊外無法繼承, 而 open 則可以任意繼承, 公開度來說, public < open

6. guard 的使用場景

swift 的語法糖之一

//當(條件) 為false 的時候進入{}
guard 條件
{
        
}

7.if let 語法糖使用場景

swift 中因為有optional,所以需要經(jīng)常判空,舉例說明if let 解決了什么問題

//不使用if let
func doSometing(str: String?){
    ...
}
let value :String ! = str
if value != ni {
     //如果value 不為 nil進入大括號執(zhí)行
}

//使用了if let 簡潔了很多
func doSometing(str: String?){
     ...
}
if let value = str {
    //如果value 不為 nil進入大括號執(zhí)行
}

8.defer的使用場景

defer 語句塊中的代碼, 會在當前作用域結(jié)束前調(diào)用, 常用場景如異常退出后, 關(guān)閉數(shù)據(jù)庫連接

func someQuery() -> ([Result], [Result]){
    //假如打開數(shù)據(jù)庫失敗        
    let db = DBOpen("xxx")
    defer {
        db.close()
    }
    //或者 查詢失敗導致異常退出 調(diào)用defer,執(zhí)行里面的代碼
    guard results1 = db.query("query1") else {
        return nil
    }
    guard results2 = db.query("query2") else {
        return nil
    }
    return (results1, results2)
}

9.String 與 NSString 的關(guān)系與區(qū)別

NSString 與 String 之間可以隨意轉(zhuǎn)換

let someString = "123"
let someNSString = NSString(string: "n123")
let strintToNSString = someString as NSString
let nsstringToString = someNSString as String

10.associatedtype 的作用

簡單來說就是 protocol 使用的泛型
例如定義一個列表協(xié)議

protocol ListProtcol {
    associatedtype Element
    func push(_ element:Element)
    func pop(_ element:Element) -> Element?
}

實現(xiàn)協(xié)議的時候, 可以使用 typealias 指定為特定的類型, 也可以自動推斷, 如

class IntList: ListProtcol {
    typealias Element = Int // 使用 typealias 指定為 Int
    var list = [Element]()
    func push(_ element: Element) {
        self.list.append(element)
    }
    func pop(_ element: Element) -> Element? {
        return self.list.popLast()
    }
}
class DoubleList: ListProtcol {
    var list = [Double]()
    func push(_ element: Double) {// 自動推斷
        self.list.append(element)
    }
    func pop(_ element: Double) -> Double? {
        return self.list.popLast()
    }
}

11.關(guān)于泛型的使用

class AnyList<T>: ListProtcol {
    var list = [T]()
    func push(_ element: T) {
        self.list.append(element)
    }
    func pop(_ element: T) -> T? {
        return self.list.popLast()
    }
}

12.可以使用 where 字句限定 Element 類型, 如:

extension ListProtcol where Element == Int {
    func isInt() ->Bool {
        return true
    }
}

13. ?? 的用法

可選值的默認值, 當可選值為nil 的時候, 會返回后面的值. 如

let someValue = optional1 ?? 0

14. lazy 的用法

swift 中的懶加載,只有被調(diào)用到的時候,才初始化和賦值

class LazyClass {
    lazy var someLazyValue: Int = {
        print("lazy init value")
        return 1
    }()
    var someNormalValue: Int = {
        print("normal init value")
        return 2
    }()
}
let lazyInstance = LazyClass()
print(lazyInstance.someNormalValue)
print(lazyInstance.someLazyValue)

15.swift block循環(huán)引用解決

在其參數(shù)前面使用[weak self]或者[unowned self]

let emtyOb = Observable<String>.empty()
_ = emtyOb.subscribe(onNext: { [weak self] (number) in
    
    print("訂閱:",number)
    self.label.text = number
})

16. dynamic 的用法

由于 swift 是一個靜態(tài)語言, 所以沒有 Objective-C 中的消息發(fā)送這些動態(tài)機制, dynamic 的作用就是讓 swift 代碼也能有 Objective-C 中的動態(tài)機制, 常用的地方就是 KVO 了, 如果要監(jiān)控一個屬性, 則必須要標記為 dynamic, 可以參考文章http://m.itdecent.cn/p/ae26100b9edf

什么時候使用 @objc
@objc 用途是為了在 Objective-C 和 Swift 混編的時候, 能夠正常調(diào)用 Swift 代碼. 可以用于修飾類, 協(xié)議, 方法, 屬性.
常用的地方是在定義 delegate 協(xié)議中, 會將協(xié)議中的部分方法聲明為可選方法, 需要用到@objc

@objc protocol OptionalProtocol {
    @objc optional func optionalFunc()
    func normalFunc()
}
class OptionProtocolClass: OptionalProtocol {
    func normalFunc() {
    }
}
let someOptionalDelegate: OptionalProtocol = OptionProtocolClass()
someOptionalDelegate.optionalFunc?()

17. 什么是高階函數(shù)

一個函數(shù)如果可以以某一個函數(shù)作為參數(shù), 或者是返回值, 那么這個函數(shù)就稱之為高階函數(shù), 如 map, reduce, filter

18. static 和 class 有什么區(qū)別

static 定義的方法不可以被子類繼承, class 則可以

class AnotherClass {
    static func staticMethod(){}
    class func classMethod(){}
}
class ChildOfAnotherClass: AnotherClass {
    override class func classMethod(){}
    //override static func staticMethod(){}// error
}

19.枚舉定義

與OC不一樣,Swift的枚舉擴展性很強了,OC只能玩Int,swift 支持

整型(Integer)
浮點數(shù)(Float Point)
字符串(String)
布爾類型(Boolean)

enum Movement {
    case letf
    case right
    case top
    case bottom
}
enum Area: String {
    case Dong = "dong"
    case Nan = "nan"
    case Xi = "xi"
    case Bei = "bei"
}

//嵌套枚舉
enum Area {
    enum DongGuan {
        case NanCheng
        case DongCheng
    }
    
    enum GuangZhou {
        case TianHe
        case CheBei
    }
}

//枚舉關(guān)聯(lián)值
enum Trade {
    case Buy(stock:String,amount:Int)
    case Sell(stock:String,amount:Int)
}

let trade = Trade.Buy(stock: "003100", amount: 100)

switch trade {
case .Buy(let stock,let amount):
    
    print("stock:\(stock),amount:\(amount)")
    
case .Sell(let stock,let amount):
    print("stock:\(stock),amount:\(amount)")
default:
    ()
}

20. swift中set 、get 方法

swift 中的set 和 get 要復雜一點。 在swift 中主要分存儲型屬性計算型屬性 這兩種 , 一般 我們只是給計算屬性添加 get\set 重寫

var command:Int {
    get {
        //return command; 會導致死循環(huán)
        //return self.command; 會導致死循環(huán)
        //return _command; 會導致死循環(huán)
        //且不能像OC那樣 return _command;
        return 1
    }
    set {
        //新值 newValue
        //value 為一個外部屬性變量
        value = newValue
    }
}

//為了解決儲型屬性的set、get 方法問題
var _command:int?
var command :Int {
    get {
       return _command 
    }
    set {
       _command = newValue 
    }
}

21. swift 中 willset 和didset 方法

屬性初始化的時候,willSet 和didSet 不會調(diào)用,只有在初始化上下文之外,屬性發(fā)生改變的時候調(diào)用;
給屬性添加觀察者屬性的時候,必須聲明屬性類型,否則編譯會報錯;

var command :Int {
    willSet {
       print("newValue is \(newValue)")
    }
    didSet {
      print("newValue is \(newValue)")
      print("oldValue is \(oldValue)")
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容