美文网首页swiftiOS
Swift - 自定义一个Sequence类型进行迭代操作.

Swift - 自定义一个Sequence类型进行迭代操作.

作者: Zafir_zzf | 来源:发表于2018-01-08 16:53 被阅读115次

    Sequence 协议是集合类型结构中的基础. 我们经常会对一个Array 或者Dictionary进行for 循环迭代正是因为它们遵守了Sequence协议并实现了迭代方法.
    自然是一个协议,我们可以自定义一个类型来遵守它,也可以实现自己想要的迭代操作.
    比如当前有一个整数10086, 有需求要取出这个数中从个位,十位,百位..到最高位的数..如果是字符串"10086" 我们可以直接对字符串序列进行遍历

        for i in "10086" {
            print(i)
         }
    

    在Swift标准库总String类型是遵守了Sequence协议的,上图代码会根据字符串索引从第0个打印到它最后一个.
    然而如果我们直接对10086这个int类型的整数进行for in 操作,编译器会告诉我们Type 'Int' does not conform to protocol 'Sequence'
    没错,Int 当然不是一个序列.不遵守这个协议,无法进行迭代操作.

    我们先来看一下Sequence协议是怎么定义的

    protocol Sequence {
        associatedtype Iterator: IteratorProtocol
        func makeIterator() -> Iterator
    }
    
    

    满足一个Sequence协议的要求只有一个,,提供一个满足IteratorProtocol协议(迭代器协议)返回值的方法..很直接,我们实现它的目的也正是为了迭代.

    /// InteratorProtocol 的定义如下
    protocol IteratorProtocol {
        associatedtype Element
        mutating func next() -> Element?
    }
    

    关联类型 Element 指定了迭代器产生的值的类型. 比如String的迭代器的元素类型是Character. 在处理Sequence的泛型约束的时候我们经常会使用Iterator.Element, 这里的Element就是IteratorProtocl中定义的..
    这个协议中只有一个 next方法,用来返回迭代的元素.可以使用for循环遍历的原因是for循环在背后帮我们做了一件事就是不断的调用迭代器的next方法,直到返回nil为止,

    /// for循环做的事情实际是下面这个的简写模式
     var iterator = someSequence.makeIterator()
            while let element = iterator.next() {
                print(element)
            }
    

    接下来完成我们的需求:

    // 因为遍历一个Int的迭代器系统中没有,需要我们自己创建
    struct NumberIterator: IteratorProtocol {
        typealias Element = Int
        var number: Int
        var offset = 1
        init(_ number: Int) {
            self.number = number
        }
        // IteratorPtocol中要求实现的函数
        mutating func next() -> NumberIterator.Element? {
        // 根据当前的offset返回个位/十位...数
            guard number / offset >= 1 else {return nil}
            offset = offset * 10
            return number / (offset / 10) % 10
        }
    }
    
    // 我们直接使用的序列
    struct NumberSequence: Sequence {
        let number: Int // 其中只有一个int型的属性
        // Sequence要求实现的函数,返回一个迭代器,把我们刚才实现的迭代器返回.当然迭代器需要一个number值.
        func makeIterator() -> NumberInterator {
            return NumberInterator(number)
        }
    }
    

    现在我们成功创建好了自己的序列类型 NumberSequence,想要直接迭代一个Int类型的整数:

            for prefix in NumberSequence(193835) {
                print(prefix)
            }
    

    直接转换成新的Sequence类型就可以进行迭代了..
    在实际应用中,如果想要迭代某一个数据类型,让它遵守Sequence协议并且实现响应的方法就可以了.

    相关文章

      网友评论

        本文标题:Swift - 自定义一个Sequence类型进行迭代操作.

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