美文网首页Swift编程
swift 小知识点汇总

swift 小知识点汇总

作者: pengxiaochao | 来源:发表于2020-03-02 16:02 被阅读0次

    1. class 和 struct 的区别

    class 为类, struct 为结构体, 类是引用类型, 结构体为值类型, 结构体不可以继承
    

    2.map、filter、reduce 的作用

    map 用于映射, 可以将一个列表转换为另一个列表

    [1, 2, 3].map{"\($0)"}// 数字数组转换为字符串数组
    //["1", "2", "3"]
    

    filter 用于过滤, 可以筛选出想要的元素

    [1, 2, 3].filter{$0 % 2 == 0} // 筛选偶数
    //[2]
    

    reduce 合并

    [1, 2, 3].reduce(""){$0 + "\($1)"}// 转换为字符串并拼接
    //"123"
    

    3.map 与 flatmap 的区别

    flatmap 有两个实现函数实现

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

    这个方法, 中间的函数返回值为一个可选值, 而 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]
    

    另一个实现
    public func flatMap<SegmentOfResult>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Iterator.Element] where SegmentOfResult : Sequence
    中间的函数, 返回值为一个数组, 而这个 flapmap 返回的对象则是一个与自己元素类型相同的数组

    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]
    

    其实这个实现, 相当于是在使用 map 之后, 再将各个数组拼起来一样的

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

    4.如何获取当前代码的函数名和行号

    file 用于获取当前文件文件名

    line 用于获取当前行号

    column 用于获取当前列编号

    function 用于获取当前函数名

    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 五种访问控制的权限

    //1.当private 或fileprivate 修饰属性的时候
    privte 修饰的属性只能在本类的作用域且在当前文件内能访问
    fileprivate 修饰的属性只能在当前文件内访问到,不管是否在本类作用域
    
    //2. fileprivate 修饰方法的时候
    fileprivate 修饰的方法,类的外部无法调用
    fileprivate 修饰方法,子类定义的同一个文件中,可以访问
    fileprivate 修饰方法,子类定义不在同一个文件,不可以访问
    
    
    //3.public 和 open 的区别
    这两个都用于在模块中声明需要对外界暴露的函数, 区别在于, public 修饰的类, 在模块外无法继承, 而 open 则可以任意继承, 公开度来说, public < open
    

    6. guard 的使用场景

    swift 的语法糖之一

    //当(条件) 为false 的时候进入{}
    guard 条件
    {
            
    }
    

    7.if let 语法糖使用场景

    swift 中因为有optional,所以需要经常判空,举例说明if let 解决了什么问题

    //不使用if let
    func doSometing(str: String?){
        ...
    }
    let value :String ! = str
    if value != ni {
         //如果value 不为 nil进入大括号执行
    }
    
    //使用了if let 简洁了很多
    func doSometing(str: String?){
         ...
    }
    if let value = str {
        //如果value 不为 nil进入大括号执行
    }
    

    8.defer的使用场景

    defer 语句块中的代码, 会在当前作用域结束前调用, 常用场景如异常退出后, 关闭数据库连接

    func someQuery() -> ([Result], [Result]){
        //假如打开数据库失败        
        let db = DBOpen("xxx")
        defer {
            db.close()
        }
        //或者 查询失败导致异常退出 调用defer,执行里面的代码
        guard results1 = db.query("query1") else {
            return nil
        }
        guard results2 = db.query("query2") else {
            return nil
        }
        return (results1, results2)
    }
    

    9.String 与 NSString 的关系与区别

    NSString 与 String 之间可以随意转换

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

    10.associatedtype 的作用

    简单来说就是 protocol 使用的泛型
    例如定义一个列表协议

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

    实现协议的时候, 可以使用 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.关于泛型的使用

    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 中的懒加载,只有被调用到的时候,才初始化和赋值

    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循环引用解决

    在其参数前面使用[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 是一个静态语言, 所以没有 Objective-C 中的消息发送这些动态机制, dynamic 的作用就是让 swift 代码也能有 Objective-C 中的动态机制, 常用的地方就是 KVO 了, 如果要监控一个属性, 则必须要标记为 dynamic, 可以参考文章http://www.jianshu.com/p/ae26100b9edf

    什么时候使用 @objc
    @objc 用途是为了在 Objective-C 和 Swift 混编的时候, 能够正常调用 Swift 代码. 可以用于修饰类, 协议, 方法, 属性.
    常用的地方是在定义 delegate 协议中, 会将协议中的部分方法声明为可选方法, 需要用到@objc

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

    17. 什么是高阶函数

    一个函数如果可以以某一个函数作为参数, 或者是返回值, 那么这个函数就称之为高阶函数, 如 map, reduce, filter

    18. static 和 class 有什么区别

    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)
    浮点数(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
        }
    }
    
    //枚举关联值
    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; 会导致死循环
            //return self.command; 会导致死循环
            //return _command; 会导致死循环
            //且不能像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 不会调用,只有在初始化上下文之外,属性发生改变的时候调用;
    给属性添加观察者属性的时候,必须声明属性类型,否则编译会报错;

    var command :Int {
        willSet {
           print("newValue is \(newValue)")
        }
        didSet {
          print("newValue is \(newValue)")
          print("oldValue is \(oldValue)")
        }
    }

    相关文章

      网友评论

        本文标题:swift 小知识点汇总

        本文链接:https://www.haomeiwen.com/subject/chjvkhtx.html