美文网首页
[swift 进阶]读书笔记-集合类型协议 C3P1_序列

[swift 进阶]读书笔记-集合类型协议 C3P1_序列

作者: liaoworkinn | 来源:发表于2018-12-17 13:14 被阅读2次

    集合类型协议


    3.1序列: sequence

    知识点1:满足sequence协议只需提供一个返回迭代器(iterator):的makeIterator方法。 集合<-Sequence<-Iterator

    迭代器:Iterator


    里面只有一个方法next( )

    public protocol IteratorProtocol {
        ///关联类型 Element 指定了迭代器产生的值的类型 
        ///如 subViews的迭代原生类型就是View 可以不用写,编译器根据next()的返回值自动判断。
        associatedtype Element
        
        ///你只需要在每次调用的时候返回下一个值,结束时返回nil
        public mutating func next() -> Self.Element?
    }
    

    next( )方法是用 mutating 关键字修饰。 几乎所有的迭代器都要求是可变状态,这样才可以管理在序列中的当前位置----(这句话的意思到现在还没太理解。大家可以把自己的理解写上了,thanks~)

    下面我们用迭代器写一个斐波那契数列(0,1,1,2,3,5,8,13.....)。

    struct FibsNumIterator:IteratorProtocol {
        var startNum = (0, 1)
        mutating func next() -> Int? {
            let nextNum = startNum.0
            startNum = (startNum.1, startNum.0 + startNum.1)
            return nextNum
        }
    }
    

    这个迭代器不返回nil, 就会产生无穷的数组。 程序会因为类型溢出而crash。

    注:迭代器是单向结构,只能按照增加的方向前进,不能倒退或者重置。

    准守序列(sequence)协议


    下面我们通过一个打印一个字符串所有前缀的demo 通过自定义迭代器自定义集合去写一个属于你的集合~

    第一步: 创建一个迭代器(Iterator)

    struct PrefixStrIterator:IteratorProtocol {
        var string: String
        var offset: String.Index
        init(string:String) {
            self.string = string
            offset = string.startIndex
        }
        ///写协议方法
        mutating func next() -> String? {
            guard offset < string.endIndex else { return nil}
            offset = string.index(after: offset)
            return String(string[string.startIndex..<offset])
        }
    }
    

    第二步: 创建一个使用这个迭代器的序列(sequence)

    ///step2.创建一个属于你的集合
    struct PrefixSequence: Sequence {
        var string: String
        
        ///协议方法:返回一个迭代器
        func makeIterator() -> PrefixStrIterator {
            return PrefixStrIterator(string: string)
        }
    }
    

    第三步: run~

            ///myfirstSquence 我的第一个集合
            for prefixStr in PrefixSequence(string: "Hi~LiaoWorking!") {
                print(prefixStr)
    //            H
    //            Hi
    //            Hi~
    //            Hi~L
    //            Hi~Li
    //            Hi~Lia
    //            Hi~Liao
    //            Hi~LiaoW
    //            Hi~LiaoWo
    //            Hi~LiaoWor
    //            Hi~LiaoWork
    //            Hi~LiaoWorki
    //            Hi~LiaoWorkin
    //            Hi~LiaoWorking
    //            Hi~LiaoWorking!
            }
    

    迭代器和值语义


    先说说值语义和引用语义,这两个定义无论在今后的学习还是日常开发细节中会经常遇到~ 敲黑板!

    作用对象 特性
    值语义 struct,应该还有其他类型。待补充。 赋值时不存在引用,复制了一份过去了
    引用语义 class 赋值时存在引用

    注:但AnyIterator这个是引用对象。。(协议章中的类型抹消的内容我们再具体说~)

    基于函数的迭代器和序列


    继续写一个Demo: AnyIterator还有一个初始化方法就是直接接受next()函数来当做参数。然后通过引用语义的特性,我们可以不创建新的类型就写一个斐波那契迭代器

    /// 通过引用语义的特性写斐波那契
    func fibsIterator() -> AnyIterator<Any> {
        var startNum = (0, 1)
        return AnyIterator{
            let nextNum = startNum.0
                startNum = (startNum.1 , startNum.0 + startNum.1)
            return nextNum
        }
    }
    

    这个是高阶知识点,的确没有第二章的生动。了解一下也挺好啊~~

    无限序列


    序列可以是无限的,而集合是有限的。

    不稳定序列


    Sequence文档明确指出序列并不保证能被多次遍历。
    原因是Sequence协议并不关心里面的序列元素会不会销毁。

    知识点1:这就是为什么在集合类型中.first 在序列中并不存在。

    序列sequence和迭代器Iterator的关系

    迭代器Iterator可以看成即将返回的元素组成的不稳定序列sequence

    子序列


    Sequence还有一个关联类型 SubSequence

    在返回原序列Sequence的切片slice操作中,SubSequence会被当做返回值的子类。

    SubSequence 有一些常用方法

    prefix 
    suffix
    dropFirst
    dropLast
    split
    

    在项目中其实经常会遇到SubSequence,如string的SubSequence等等。。(哈哈才一个,这个不能叫“经常”。其实是会经常遇到SubSequence。不过一时之间想不起来了😅)

    文章源文件地址

    相关文章

      网友评论

          本文标题:[swift 进阶]读书笔记-集合类型协议 C3P1_序列

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