Flo*_*ian 33 swift swift2 swift3
我在Swift中有一个自定义的OptionSetType结构.如何枚举实例的所有值?
这是我的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)
}
Run Code Online (Sandbox Code Playgroud)
我想这样的事情:
let weekdays: WeekdaySet = [.Monday, .Tuesday]
for weekday in weekdays {
// Do something with weekday
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*n R 41
从Swift 4开始,标准库中没有方法可以枚举OptionSetType(Swift 2)resp 的元素.
OptionSet(斯威夫特3,4).
这是一种可能的实现,它简单地检查底层原始值的每个位,并且对于设置的每个位,返回相应的元素."溢出乘法" &* 2用作左移,因为<<仅针对具体的整数类型定义,但不针对IntegerType协议定义.
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
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
let weekdays: WeekdaySet = [.Monday, .Tuesday]
for weekday in weekdays.elements() {
print(weekday)
}
// Output:
// WeekdaySet(rawValue: 2)
// WeekdaySet(rawValue: 4)
Run Code Online (Sandbox Code Playgroud)
斯威夫特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
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
斯威夫特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
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
mil*_*ilo 11
基于之前的答案,我创建了一个通用的Swift 4解决方案IteratorProtocol:
public struct OptionSetIterator<Element: OptionSet>: IteratorProtocol where Element.RawValue == Int {
private let value: Element
public init(element: Element) {
self.value = element
}
private lazy var remainingBits = value.rawValue
private var bitMask = 1
public mutating func next() -> Element? {
while remainingBits != 0 {
defer { bitMask = bitMask &* 2 }
if remainingBits & bitMask != 0 {
remainingBits = remainingBits & ~bitMask
return Element(rawValue: bitMask)
}
}
return nil
}
}
Run Code Online (Sandbox Code Playgroud)
比在OptionSet扩展工具中 makeIterator()
假设你的OptionSets将是Int:
extension OptionSet where Self.RawValue == Int {
public func makeIterator() -> OptionSetIterator<Self> {
return OptionSetIterator(element: self)
}
}
Run Code Online (Sandbox Code Playgroud)
现在每次创建一个OptionSet时,只需遵守它Sequence.
struct WeekdaySet: OptionSet, Sequence {
let rawValue: Int
...
}
Run Code Online (Sandbox Code Playgroud)
您现在应该可以迭代它:
let weekdays: WeekdaySet = [.monday, .tuesday]
for weekday in weekdays {
// Do something with weekday
}
Run Code Online (Sandbox Code Playgroud)
我还创建了一个类型,以明确使用的内容:
typealias SequenceOptionSet = OptionSet & Sequence
| 归档时间: |
|
| 查看次数: |
6352 次 |
| 最近记录: |