Swift中导入的NS_选项(RawOptionSetType)的开关语句?
Swift中的switch语句更具表现力。我想知道这是否可能: 例如,让我们看看UIViewAutoResize。目标C中对其定义如下:Swift中导入的NS_选项(RawOptionSetType)的开关语句?,swift,switch-statement,enumeration,Swift,Switch Statement,Enumeration,Swift中的switch语句更具表现力。我想知道这是否可能: 例如,让我们看看UIViewAutoResize。目标C中对其定义如下: typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) { UIViewAutoresizingNone = 0, UIViewAutoresizingFlexibleLeftMargin = 1 << 0, UIViewAutoresizin
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
是否可以使用一个switch语句而不是多个if语句
if foo & UIViewAutoresizing.FlexibleHeight != nil {
}
if foo & UIViewAutoresizing.FlexibleWidth != nil {
}
if foo & UIViewAutoresizing.FlexibleTopMargin != nil {
}
类似于以下伪代码:
switch foo { // ** THIS IS PSEUDO CODE AND WILL NOT COMPILE **
case & .FlexibleHeight:
println("height")
case & .FlexibleWidth:
println("width")
case & .FlexibleTop:
println("top")
}
我昨天和今天试了几个小时,想用switch来完成这项工作,但没有成功 原因是在这种特殊情况下,我们需要针对几个案例进行测试。在Swift中,我们需要使用
fallthrough
关键字。但是,如果下一种情况使用变量,我们不允许进入下一种情况,因为我们不能使用case let where
语句,如下所示:
switch foo {
case let x where x & .FlexibleHeight != nil:
println("height")
case let x where x & .FlexibleWidth != nil:
println("width")
case let x where x & .FlexibleTopMargin != nil:
println("top margin")
default:
println("no")
}
一旦案件触发,就会发生这种情况。但是
switch foo {
case let x where x & .FlexibleHeight != nil:
println("height")
fallthrough
case let x where x & .FlexibleWidth != nil:
println("width")
fallthrough
case let x where x & .FlexibleTopMargin != nil:
println("top margin")
default:
println("no")
}
由于上述原因不起作用
我会用一个清晰的if语句,比如
let foo = UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleHeight
let width = foo & UIViewAutoresizing.FlexibleWidth;
let height = foo & UIViewAutoresizing.FlexibleHeight;
if width == .FlexibleWidth {
println("width")
}
if height == .FlexibleHeight {
println("height")
}
或
当然可以,尽管现在
rawtoptionsetype
没有实现BooleanType
协议有点复杂
switch foo {
case let x where x & .FlexibleHeight != nil:
println("height")
case let x where x & .FlexibleWidth != nil:
println("width")
case let x where x & .FlexibleTopMargin != nil:
println("top margin")
default:
println("no")
}
请注意,这将在第一个匹配的条件下停止!所以这实际上是另一种形式:
if foo & .FlexibleHeight != nil {
println("height")
} else if foo & .FlexibleWidth != nil {
println("width")
} else if foo & .FlexibleTopMargin != nil {
println("top margin")
}
我提出的另一个解决方案是:
let foo = /* .. your value to test .. */
let allCases = [UIViewAutoresizing.FlexibleHeight, UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleTopMargin]
for oneCase in allCases {
switch oneCase & foo {
case UIViewAutoresizing.FlexibleHeight:
println("height")
case UIViewAutoresizing.FlexibleWidth:
println("width")
case UIViewAutoresizing.FlexibleTopMargin:
println("top")
default:
break
}
}
我对这个问题感到非常沮丧,因此我编写了一个
位掩码
类来处理这些用例。代码在Github上:
它允许您使用任何类型的对象作为基础类型来执行类似的操作(这里我使用的是enum
):
enum属性:IBitmask可表示,IAutoBitmaskable{
箱子大,丑,吓人
静态变量autobitmaskvalue:[MonsterAttributes]=[.Big、.ught、.thrable、]
var bitmaskValue:UInt16{return AutoBitmask..autobitmaskvalue for(self)}
init(bitmaskValue:UInt16){self=AutoBitmask.autovaluefromtmask(bitmaskValue)}
}
//初始化的各种方法
let选项:MonsterAttributes=.ught
让bitmaskOfOption=位掩码(选项)
让另一个bitmaskOfOption=| MonsterAttributes.ught//与bitmaskOfOption相同
设orWithVar=option |.Big/==Bitmask值为1 | 2的位掩码
设simpleOr=MonsterAttributes.Big |.ught/==Bitmask值为1 | 2的位掩码
//获取原始整数位掩码值
设simpleOrValue=simpleOr.bitmaskValue/==UInt16(1 | 2)
设orValue=(MonsterAttributes.Big |.丑陋)。bitmaskValue/==UInt16(1 | 2)
//实现布尔类型
如果simpleOr&.ught{/*此代码将执行*/}
//支持模式匹配操作符
如果simpleOr~=.ught{/*此代码将执行*/}
如果simpleOr~=(.ught |.trustry){/*此代码将执行*/}
。。。你所要做的就是实现一个单一属性的协议
switch foo {
case let x where x & .FlexibleHeight != nil:
println("height")
case let x where x & .FlexibleWidth != nil:
println("width")
case let x where x & .FlexibleTopMargin != nil:
println("top margin")
default:
println("no")
}
我真的很好奇是否有人对代码有任何反馈或想法,所以如果你想到什么,请在队列中留下一个问题 案例let值,其中值和FlexibleHeight!=nil:但它仍然不好,
if else
语句对于上面所示的位屏蔽值没有多大意义,因为它将在第一个找到的非空位停止,但一个变量make会保留多个选项,并在那里保留多个非空位。@vikingosegundo您是对的。我想表达一些其他的东西。查看更改。您的if
级联实际上并不像您所说的那样是if
-else
级联,而是一系列独立条件。不过,这是一件好事,因为正如@vikingosegundo所指出的,这种类型的值可以设置多个标志。在这里使用switch
语句会对您造成伤害,但对您没有帮助-模式匹配仅适用于互斥选项。好吧,这不是最好的问题,但我们都是swift新手。在switch语句中,只执行一个case语句。请参阅下面我的答案,了解解决方案。在第一次匹配时停止意味着对于NS_选项来说这是一个无用的解决方案。您需要故障排除
关键字,或者如果,您需要坚持使用多个。可能会起作用,但这不是一个优雅的循环解决方案。我建议使用故障排除
关键字寻求解决方案,或者如果
,则坚持使用多个。
let foo = /* .. your value to test .. */
let allCases = [UIViewAutoresizing.FlexibleHeight, UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleTopMargin]
for oneCase in allCases {
switch oneCase & foo {
case UIViewAutoresizing.FlexibleHeight:
println("height")
case UIViewAutoresizing.FlexibleWidth:
println("width")
case UIViewAutoresizing.FlexibleTopMargin:
println("top")
default:
break
}
}
enum MonsterAttributes : IBitmaskRepresentable, IAutoBitmaskable {
case Big, Ugly, Scary
static var autoBitmaskValues : [MonsterAttributes] = [.Big, .Ugly, .Scary,]
var bitmaskValue: UInt16 { return AutoBitmask..autoBitmaskValueFor(self) }
init(bitmaskValue: UInt16) { self = AutoBitmask.autoValueFromBitmask(bitmaskValue) }
}
// various ways to initialize
let option : MonsterAttributes = .Ugly
let bitmaskOfOption = Bitmask(option)
let anotherBitmaskOfOption = |MonsterAttributes.Ugly // same as bitmaskOfOption
let orWithVar = option | .Big // == Bitmask<MonsterAttributes> with a bitmaskValue of 1 | 2
let simpleOr = MonsterAttributes.Big | .Ugly // == Bitmask<MonsterAttributes> with a bitmaskValue of 1 | 2
// getting the raw integral bitmask value
let simpleOrValue = simpleOr.bitmaskValue // == UInt16(1 | 2)
let orValue = (MonsterAttributes.Big | .Ugly).bitmaskValue // == UInt16(1 | 2)
// implements BooleanType
if simpleOr & .Ugly { /* this code will execute */ }
// supports pattern matching operator
if simpleOr ~= .Ugly { /* this code will execute */ }
if simpleOr ~= (.Ugly | .Scary) { /* this code will execute */ }