如何以易读的形式显示OptionSet值? [英] How to display OptionSet values in human-readable form?

查看:132
本文介绍了如何以易读的形式显示OptionSet值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Swift具有OptionSet类型,该类型基本上将设置操作添加到C样式位标志.苹果公司正在其框架中广泛使用它们.示例包括animate(withDuration:delay:options:animations:completion:)中的options参数.

Swift has the OptionSet type, which basically adds set operations to C-Style bit flags. Apple is using them pretty extensively in their frameworks. Examples include the options parameter in animate(withDuration:delay:options:animations:completion:).

从正面看,它使您可以使用干净的代码,例如:

On the plus side, it lets you use clean code like:

options: [.allowAnimatedContent, .curveEaseIn]

但是,也有一个缺点.

如果我想显示OptionSet的指定值,似乎没有一种干净的方法:

If I want to display the specified values of an OptionSet, there doesn't seem to be a clean way to do it:

let options: UIViewAnimationOptions = [.allowAnimatedContent, .curveEaseIn]
print("options = " + String(describing: options))

显示非常无用的消息:

options = UIViewAnimationOptions(rawValue:65664)

options = UIViewAnimationOptions(rawValue: 65664)

其中一些位字段的文档将常数表示为2的幂:

The docs for some of these bit fields expresses the constant as a power-of-two value:

flag0    = Flags(rawValue: 1 << 0)

但是我的示例OptionSet UIViewAnimationOptions的文档并没有告诉您有关这些标志的数值的任何信息,因此从十进制数字中找出位并不容易.

But the docs for my example OptionSet, UIViewAnimationOptions, doesn't tell you anything about the numeric value of these flags and figuring out bits from decimal numbers is not straightforward.

是否有一些干净的方法可以将OptionSet映射到所选值?

Is there some clean way to map an OptionSet to the selected values?

我想要的输出如下:

options = UIViewAnimationOptions([.allowAnimatedContent,.curveEaseIn])

options = UIViewAnimationOptions([.allowAnimatedContent, .curveEaseIn])

但是,如果没有一堆凌乱的代码,这将需要我维护每个标志的显示名称表,我想不出一种方法.

But I can't think of a way to do this without a bunch of messy code that would require me to maintain a table of display names for each flag.

(我对我自己的代码中创建的系统框架和自定义OptionSet都感兴趣.)

(I'm interested in doing this for both system frameworks and custom OptionSets I create in my own code.)

枚举使您既有名称又有原始值,但这些枚举不支持通过OptionSet获得的set函数.

Enums let you have both a name and a raw value for the enum, but those don't support the set functions you get with OptionSets.

推荐答案

NSHipster中的这篇文章提供了OptionSet的替代方法,它提供了OptionSet的所有功能,并且易于记录:

This article in NSHipster gives an alternative to OptionSet that offers all the features of an OptionSet, plus easy logging:

https://nshipster.com/optionset/

如果仅添加选项类型为CustomStringConvertible的要求,则可以非常清晰地记录此类型的Set.以下是NSHipster网站的代码-唯一的变化是对Option类添加了CustomStringConvertible一致性

If you simply add a requirement that the Option type be CustomStringConvertible, you can log Sets of this type very cleanly. Below is the code from the NSHipster site - the only change being the addition of CustomStringConvertible conformance to the Option class

protocol Option: RawRepresentable, Hashable, CaseIterable, CustomStringConvertible {}

enum Topping: String, Option {
    case pepperoni, onions, bacon,
    extraCheese, greenPeppers, pineapple

    //I added this computed property to make the class conform to CustomStringConvertible
    var description: String {
        return ".\(self.rawValue)"
    }
}

extension Set where Element == Topping {
    static var meatLovers: Set<Topping> {
        return [.pepperoni, .bacon]
    }

    static var hawaiian: Set<Topping> {
        return [.pineapple, .bacon]
    }

    static var all: Set<Topping> {
        return Set(Element.allCases)
    }
}

typealias Toppings = Set<Topping>

extension Set where Element: Option {
    var rawValue: Int {
        var rawValue = 0
        for (index, element) in Element.allCases.enumerated() {
            if self.contains(element) {
                rawValue |= (1 << index)
            }
        }
        return rawValue
    }
}

然后使用它:

let toppings: Set<Topping> = [.onions, .bacon]

print("toppings = \(toppings), rawValue = \(toppings.rawValue)")

输出

浇头= [.onions,.bacon],rawValue = 6

toppings = [.onions, .bacon], rawValue = 6

就像您想要的那样.

之所以可行,是因为Set将其成员显示为方括号内的逗号分隔列表,并使用每个Set成员的description属性来显示该成员. description属性仅显示带有.前缀的每个项目(枚举的名称为String)

That works because a Set displays its members as a comma-delimited list inside square brackets, and uses the description property of each set member to display that member. The description property simply displays each item (the enum's name as a String) with a . prefix

并且由于Set<Option>的rawValue与具有相同值列表的OptionSet相同,因此您可以轻松地在它们之间进行转换.

And since the rawValue of a Set<Option> is the same as an OptionSet with the same list of values, you can convert between them readily.

我希望Swift可以使它成为OptionSet s的母语功能.

I wish Swift would just make this a native language feature for OptionSets.

这篇关于如何以易读的形式显示OptionSet值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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