Swift中的switch语句更具表现力。我想知道这是否可行:
让我们看一下UIViewAutoresizing。它在Objective-C中的定义如下:
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
};
我可以像在枚举中一样在Swift中使用它:
let foo = UIViewAutoresizing([.FlexibleHeight, .FlexibleTopMargin])
是否可以使用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")
}
答案 0 :(得分:1)
我昨天和今天试了好几个小时才开始工作 - 没有成功。
原因是在这种特殊情况下我们需要针对几种情况进行测试。在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")
}
或
let foo = UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleHeight
let usesFlexibleWidth = (foo & UIViewAutoresizing.FlexibleWidth) != nil;
let usesFlexibleHeight = (foo & UIViewAutoresizing.FlexibleHeight) != nil;
if usesFlexibleWidth {
println("width")
}
if usesFlexibleHeight {
println("height")
}
答案 1 :(得分:1)
我对这个问题感到很沮丧,我编写了一个可以处理这些用例的Bitmask<T>
类。代码在Github上发布:brynbellomy/SwiftBitmask
它允许你用任何类型的对象作为基础类型(这里我使用的是enum
)来做这样的事情:
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 */ }
...而你所要做的就是实现一个属性协议。
如果有人对代码有任何反馈意见或想法,我真的很好奇,所以如果您有任何想法,请在队列中留下问题!
答案 2 :(得分:0)
你绝对可以,虽然RawOptionSetType
没有实现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")
}
答案 3 :(得分:0)
我想出的另一个解决方案是:
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
}
}