你如何在 Swift 中枚举 OptionSetType? [英] How do you enumerate OptionSetType in Swift?

查看:15
本文介绍了你如何在 Swift 中枚举 OptionSetType?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Swift 中有一个自定义的 OptionSetType 结构.如何枚举实例的所有值?

I have a custom OptionSetType struct in Swift. How can I enumerate all values of an instance?

这是我的 OptionSetType:

This is my OptionSetType:

struct WeekdaySet: OptionSetType {
    let rawValue: UInt8

    init(rawValue: UInt8) {
        self.rawValue = rawValue
    }

    static let Sunday        = WeekdaySet(rawValue: 1 << 0)
    static let Monday        = WeekdaySet(rawValue: 1 << 1)
    static let Tuesday       = WeekdaySet(rawValue: 1 << 2)
    static let Wednesday     = WeekdaySet(rawValue: 1 << 3)
    static let Thursday      = WeekdaySet(rawValue: 1 << 4)
    static let Friday        = WeekdaySet(rawValue: 1 << 5)
    static let Saturday      = WeekdaySet(rawValue: 1 << 6)
}

我想要这样的东西:

let weekdays: WeekdaySet = [.Monday, .Tuesday]
for weekday in weekdays {
    // Do something with weekday
}

推荐答案

从 Swift 4 开始,标准库中没有方法枚举 OptionSetType (Swift 2) 的元素.OptionSet (Swift 3, 4).

As of Swift 4, there are no methods in the standard library to enumerate the elements of an OptionSetType (Swift 2) resp. OptionSet (Swift 3, 4).

这是一个可能的实现,它简单地检查每一位基础原始值的,对于设置的每个位,返回相应的元素.溢出乘法" &* 2 被用作左移,因为 << 仅针对具体整数类型定义,而不针对 IntegerType 协议.

Here is a possible implementation which simply checks each bit of the underlying raw value, and for each bit which is set, the corresponding element is returned. The "overflow multiplication" &* 2 is used as left-shift because << is only defined for the concrete integer types, but not for the IntegerType protocol.

Swift 2.2:

public extension OptionSetType where RawValue : IntegerType {

    func elements() -> AnySequence<Self> {
        var remainingBits = self.rawValue
        var bitMask: RawValue = 1
        return AnySequence {
            return AnyGenerator {
                while remainingBits != 0 {
                    defer { bitMask = bitMask &* 2 }
                    if remainingBits & bitMask != 0 {
                        remainingBits = remainingBits & ~bitMask
                        return Self(rawValue: bitMask)
                    }
                }
                return nil
            }
        }
    }
}

示例用法:

let weekdays: WeekdaySet = [.Monday, .Tuesday]
for weekday in weekdays.elements() {
    print(weekday)
}

// Output:
// WeekdaySet(rawValue: 2)
// WeekdaySet(rawValue: 4)

Swift 3:

public extension OptionSet where RawValue : Integer {

    func elements() -> AnySequence<Self> {
        var remainingBits = rawValue
        var bitMask: RawValue = 1
        return AnySequence {
            return AnyIterator {
                while remainingBits != 0 {
                    defer { bitMask = bitMask &* 2 }
                    if remainingBits & bitMask != 0 {
                        remainingBits = remainingBits & ~bitMask
                        return Self(rawValue: bitMask)
                    }
                }
                return nil
            }
        }
    }
}

Swift 4:

public extension OptionSet where RawValue: FixedWidthInteger {

    func elements() -> AnySequence<Self> {
        var remainingBits = rawValue
        var bitMask: RawValue = 1
        return AnySequence {
            return AnyIterator {
                while remainingBits != 0 {
                    defer { bitMask = bitMask &* 2 }
                    if remainingBits & bitMask != 0 {
                        remainingBits = remainingBits & ~bitMask
                        return Self(rawValue: bitMask)
                    }
                }
                return nil
            }
        }
    }
}

这篇关于你如何在 Swift 中枚举 OptionSetType?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆