swift function or closure with pre-filled parameter - swift2

I have a class that takes a completion handler. Can I pre-fill some the parameters? The completion handler is a function itself rather than a closure.
func completionHandler(value: Int, value2: Int)
{
print(value + value2)
}
func run() {
let handler = completionHandler
handler(9, value2: 7) //runs the handler
someinstance.handler = handler //someinstance will eventually run the handler
let handler2 = completionHandler(9) //is this possible?
someinstance2.handler = handler2 //is this possible?
someinstance3.handler = { a,b in return a+b } //also fine
}

You could, technically, define a handler for you completion handler, for cases when you want to make use of a default value for value or value2 in completionHandler.
func completionHandler(value: Int, _ value2: Int) {
print(value + value2)
}
func defaultValueHandler(defaultValue: Int? = nil, defaultValue2: Int? = nil) -> ((Int) -> ()) {
if let defaultValue2 = defaultValue2 {
return { value in completionHandler(value, defaultValue2) }
}
else if let defaultValue = defaultValue {
return { value in completionHandler(defaultValue, value) }
}
return { _ in print("Invalid use: supply a single non-nil default value.") }
}
var handler = defaultValueHandler(9) // default value for 'value'
handler(5) // calls foo(9, 5), prints 14
handler = defaultValueHandler(nil, defaultValue2: 11) // default value for 'value2'
handler(5) // calls foo(5, 11), prints 16
The use of this is, for your case, probably limited in practice. The handler closure instance above will be of type (Int) -> () as compared to e.g. completionHandler function which is of type (Int, Int) -> (). So if someinstance.handler (in your example) expects the latter, you'll be in trouble.
Now, you could modify defaultValueHandler(..) to return closures of type (Int, Int) -> (), but then you'll need to supply calls to the resulting handling closure with two arguments, where one argument will be ignored in favour of the default value you supplied when assigning a closure to the handler. Again, this technically possibly, but will most likely just confuse whomever codes, and lives near the subject of "troll coding" (e.g. not-so-appriciated 1st april insertion into the code of a colleague, "handler(2,2) == 4 // false ?!?"). Anyway:
func completionHandler(value: Int, _ value2: Int) {
print(value + value2)
}
func defaultValueHandler(defaultValue: Int? = nil, defaultValue2: Int? = nil) -> ((Int, Int) -> ()) {
if let defaultValue2 = defaultValue2 {
if defaultValue == nil {
return { value, _ in completionHandler(value, defaultValue2) }
}
}
else if let defaultValue = defaultValue {
return { _, value2 in completionHandler(defaultValue, value2) }
}
return { _ in print("Invalid use: supply a single non-nil default value.") }
}
var handler = defaultValueHandler(9)
handler(0,5) // ignores first parameter '0', calls foo(9, 5), prints 14
handler = defaultValueHandler(nil, defaultValue2: 11)
handler(5,0) // ignores second parameter '0', calls foo(5, 11), prints 16

Related

Problem about the usage of `withLatestFrom`

I am a newbie to RxSwift. I ran into a problem
The requirement is like this,
If there are values return from stream A, B and C then I emit an event on stream X (boolean)
Whenever there is true value returns from streamX, I want to take a take a snapshot of stream A, B and C and do something
Due to class design reason, we need to separate the action 1 and 2 into two Rx blocks
below is the simplified version of my code
class parent {
let streamA: BehaviorRelay<String?> = BehaviorRelay(value: nil)
let streamB: BehaviorRelay<String?> = BehaviorRelay(value: nil)
let streamC: BehaviorRelay<String?> = BehaviorRelay(value: nil)
let moduleVisibility: BehaviorRelay<Bool?> = BehaviorRelay(value: nil)
BehaviorRelay.combineLatest(streamA.filterNil(), streamB.filterNil(), streamB.filterNil()).subscribe { [weak self ] _, _, _ in
guard let self = self else { return }
self.moduleVisibility.accept(true)
}.disposed(by: bag)
}
class childClass {
moduleVisibility.filterNil().filter({ $0 == true}).withLatestFrom(Observable.combineLatest(streamA.filterNil(), streamB.filterNil(), streamC.filterNil())).observeOn(MainScheduler.instance).subscribe(onNext: { valueA, valueB, valueC in
// This line does not get called
print("\(valueA) \(valueB) \(valueC)")
}).disposed(by: bag)
}
// then I called
streamA.accept("A")
streamB.accept("B")
streamC.accept("C")
// but the block # childClass does not get fired
I check there is event from the moduleVisibility stream. but it says that there is not value from withLatestFrom block.
Would like to know if my block setup is not correct.
Cause I think A B C are causing the event of X
while there is event from X, there must be values from A B C
or I need to observe on main.thread? any help will be appreciated :pray
formatted code
import RxSwift
import RxCocoa
func ignoreNil<A>(x: A?) -> Observable<A> {
return x.map { Observable.just($0) } ?? Observable.empty()
}
class Parent {
let bag = DisposeBag()
let streamA: BehaviorRelay<String?> = BehaviorRelay(value: nil)
let streamB: BehaviorRelay<String?> = BehaviorRelay(value: nil)
let streamC: BehaviorRelay<String?> = BehaviorRelay(value: nil)
let moduleVisibility: BehaviorRelay<Bool?> = BehaviorRelay(value: nil)
init() {
BehaviorRelay
.combineLatest(
streamA.flatMap(ignoreNil),
streamB.flatMap(ignoreNil),
streamC.flatMap(ignoreNil)
).subscribe { [weak self ] _, _, _ in
guard let self = self else { return }
print("moduleVisibility ")
self.moduleVisibility.accept(true)
}.disposed(by: bag)
}
}
class Child: Parent {
override init() {
super.init()
moduleVisibility
.flatMap(ignoreNil)
.filter({ $0 == true})
.withLatestFrom(
Observable.combineLatest(
streamA,
streamB,
streamC
)
)
.subscribe(onNext: { valueA, valueB, valueC in
// This line does not get called
print("\(valueA) \(valueB) \(valueC)")
}).disposed(by: bag)
}
}
let child = Child()
child.streamA.accept("A")
child.streamB.accept("B")
child.streamC.accept("C")
/*
moduleVisibility
Optional("A") Optional("B") nil
*/
Notice in the code below how the functions I created mirror the text descriptions almost exactly. That is what you should be striving for. No need for any classes here, just a couple of functions (these functions are your view models.) Notice how they are very reusable...
// If there are values return from stream A, B and C then I emit an event on stream X (boolean)
func allEmitedValue<A, B, C>(_ a: Observable<A?>, _ b: Observable<B?>, _ c: Observable<C?>) -> Observable<Bool> {
Observable.combineLatest(a, b, c) { allContainValue($0, $1, $2) }
}
// Whenever there is true value returns from streamX, I want to take a take a snapshot of stream A, B and C and do something
func snapshot<A, B, C>(_ a: Observable<A?>, _ b: Observable<B?>, _ c: Observable<C?>) -> Observable<(A, B, C)> {
Observable.combineLatest(a, b, c)
.compactMap{ allContainValue($0.0, $0.1, $0.2) ? ($0.0!, $0.1!, $0.2!) : nil }
}
func allContainValue<A, B, C>(_ a: A?, _ b: B?, _ c: C?) -> Bool {
a != nil && b != nil && c != nil
}
If the architecture requires that you put these in classes with relays then:
class parent {
let streamA: BehaviorRelay<String?> = BehaviorRelay(value: nil)
let streamB: BehaviorRelay<String?> = BehaviorRelay(value: nil)
let streamC: BehaviorRelay<String?> = BehaviorRelay(value: nil)
let moduleVisibility: Observable<Bool>
init() {
moduleVisibility = allEmitedValue(streamA.asObservable(), streamB.asObservable(), streamC.asObservable())
}
}
class childClass: parent {
let bag = DisposeBag()
override init() {
super.init()
snapshot(streamA.asObservable(), streamB.asObservable(), streamC.asObservable())
.observe(on: MainScheduler.instance)
.subscribe(onNext: { valueA, valueB, valueC in
// now it gets called.
print("\(valueA) \(valueB) \(valueC)")
})
.disposed(by: bag)
}
}
But note:
Avoid the use of the subject types [Including Relays]. Rx is effectively a functional programming paradigm. Using subjects [or Relays] means we are now managing state, which is potentially mutating. Dealing with both mutating state and asynchronous programming at the same time is very hard to get right. Furthermore, many of the operators (extension methods) have been carefully written to ensure that correct and consistent lifetime of subscriptions and sequences is maintained; when you introduce subjects, you can break this. -- Intro to Rx
Specifically in this case, that observe(on:) is woefully inadequate in ensuring that this code handles threads correctly.

RxSwift observable creation which takes the last value of the stream itself

I am trying to use RxSwift to calculate SMA(simple moving average) and EMA(exponentially weighted moving average)
The setup is like below, the methods take the close price stream as input Observable<Double>. so every time if there is a new close price being emitted, the sma obervable will emit a new calculated value to the stream
I finished the SMA version, which is working fine
func sma(_ source: Observable<Double>, _ length: Int) -> Observable<Double?> {
let bag = DisposeBag()
return Observable<Double?>.create { observer -> Disposable in
source.scan([]) { Array($0 + [$1].suffix(length)) }.subscribe(onNext: { value in
if value.count < length {
observer.onNext(nil)
} else {
observer.onNext(value.reduce(0.0, { $0 + $1 / Double(length) }))
}
}).disposed(by: bag)
return Disposables.create()
}
}
But the EMA formula is a bit complex
https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
the formula involve the previous EMA value.
I do not have clear idea how I can get the stream last value inside a Observable creation block :thinking
below is the code I tried to implement, but .withLatestFrom(ema(source, length)) did not work out
func ema(_ source: Observable<Double>, _ length: Int) -> Observable<Double?> {
let bag = DisposeBag()
return Observable<Double?>.create { observer -> Disposable in
source.scan([]) { Array($0 + [$1].suffix(length)) }.withLatestFrom(ema(source, length)) { return ($0, $1) }
.subscribe(onNext: { value in
let alpha: Double = Double(2) / Double(length + 1)
let src = value.0
var sum: Double? = 0.0
let sum1 = value.1
sum = na(sum1) ? sma(src, length) : alpha * src.last! + (1 - alpha) * nz(sum1)
observer.onNext(sum)
}).disposed(by: bag)
return Disposables.create()
}
}
any help is greatly appreciated :pray
First let's cleanup your sma operator. You are creating dispose bags inside the function which is inappropriate. The subscribe returns a disposable and the create's closure needs to return a disposable. Just return the subscribe's disposable...
func sma(_ source: Observable<Double>, _ length: Int) -> Observable<Double?> {
Observable<Double?>.create { observer -> Disposable in
source
.scan([]) { Array($0 + [$1].suffix(length)) }
.subscribe(onNext: { value in
if value.count < length {
observer.onNext(nil)
} else {
observer.onNext(value.reduce(0.0, { $0 + $1 / Double(length) }))
}
})
}
}
But since you are outputting the same number of events as you input, we can simplify even more. Whenever you are outputting the same number of events as you input, think map.
func sma(_ source: Observable<Double>, _ length: Int) -> Observable<Double?> {
source
.scan([]) { Array($0 + [$1].suffix(length)) }
.map { value in
if value.count < length {
return nil
} else {
return value.reduce(0.0, { $0 + $1 / Double(length) })
}
}
}
And whenever you only have one Observable as input, consider making it an extension on the Observable type so it can be easily inserted into a chain...
extension ObservableType where Element == Double {
func sma(_ length: Int) -> Observable<Double?> {
scan([]) { Array($0 + [$1].suffix(length)) }
.map { $0.count < length ? nil : $0.reduce(0.0, { $0 + $1 / Double(length) }) }
}
}
Now that we have done all that, let's tackle your actual question. First express your formula as a function...
func getEMA(prices: [Double], k: Double? = nil) -> Double {
guard !prices.isEmpty else { return 0 }
let k = k ?? Double(2 / (prices.count + 1))
return prices[0] * k + getEMA(prices: prices.suffix(prices.count - 1), k: k) * (1 - k)
}
The above should be easy to test using some sample values. I'll leave you to do that. Once we have the above, we can use the same pattern you used for your sma to create the operator:
extension ObservableType where Element == Double {
func ema(_ length: Int) -> Observable<Double?> {
scan([]) { Array([$1] + $0).suffix(length) } // put the most recent price in front to correctly handle the formula
.map { $0.count < length ? nil : getEMA(prices: $0) }
}
}
I found a solution (not sure if its the cleanest way)
which is to create a BehaviourRelay inside the function declaration while outside of the Observable.create block, which keeps a local copy of the latest EMA calculated.
in this way, it does not need function's consumer to dependency inject an Observable nor having a complex stream transformation.
Below is the EMA(exponentially weighted moving average) implementation using RxSwift
func ema(_ source: Observable<Double>, _ length: Int) -> Observable<Double?> {
let bag = DisposeBag()
let lastEMA: BehaviorRelay<Double?> = BehaviorRelay.init(value: nil)
return Observable<Double?>.create { observer -> Disposable in
source.scan([]) { Array($0 + [$1].suffix(length)) }
.subscribe(onNext: { value in
let alpha: Double = Double(2) / Double(length + 1)
let src = value
var sum: Double? = 0.0
sum = na(lastEMA.value) ? sma(src, length) : alpha * src.last! + (1 - alpha) * nz(lastEMA.value)
observer.onNext(sum)
lastEMA.accept(sum)
}).disposed(by: bag)
return Disposables.create()
}
}
Remarks:
na and nz are method copied from TradingView pinescript
https://www.tradingview.com/pine-script-reference/#var_na
https://www.tradingview.com/pine-script-reference/#fun_nz
https://www.tradingview.com/pine-script-reference/#fun_ema

Swift: filter protocol array by comparing types

(first post)
usually im able to find answers here or elsewhere but no luck this time =(
Question: in Swift, how do you filter an array that is of a protocol type by an implementing type supplied as a function parameter?
protocol Aprotocol {
var number:Int { get set }
}
class Aclass: Aprotocol {
var number = 1
}
class AnotherClass: Aprotocol {
var number = 1
}
var array:[Aprotocol] = [ Aclass(), AnotherClass(), Aclass() ]
func foo (parameter:Aprotocol) -> Int {
return array.filter({ /* p in p.self == parameter.self */ }).count
}
var bar:Aprotocol = // Aclass() or AnotherClass()
var result:Int = foo(bar) // should return 2 or 1, depending on bar type
maybe this is not the right approach at all?
thanks!
Here is what I think you want:
return array.filter { (element: Aprotocol) -> Bool in
element.dynamicType == parameter.dynamicType
}.count
But I recommend this, which does the same, but without the useless instance of Aclass() which is passed in the answer on the top. Also this way is faster:
func foo <T: Aprotocol>(type: T.Type) -> Int {
return array.filter { (element: Aprotocol) -> Bool in
element.dynamicType == type
}.count
}
var result:Int = foo(Aclass)
The dynamicType will return the Type of an instance
Very easy:
return array.filter({ parameter.number == $0.number }).count
Kametrixoms solution works (if you use "is T" instead of "== type") but in my case, since i didnt know which implementing class was going to call it, had to go with this solution:
protocol Aprotocol: AnyObject {
var number:Int { get set }
}
class func foo(parameter: AnyObject) -> Int {
return array.filter ({ (element: Aprotocol) -> Bool in
object_getClassName(element) == object_getClassName(parameter)
}).count
}

Swift, Equatable protocol bug?

I am building a very simple structure in Swift that contains an array of optional values. This struct must conform to the Equatable protocol. This is the code:
struct MyTable: Equatable {
var values: [Int?] = Array(count: 64, repeatedValue: nil)
}
func == (lhs: MyTable, rhs: MyTable) -> Bool {
return lhs.values == rhs.values
}
Quite simple. I see no mistakes, but the compiler gives error: "'[Int?]' is not convertible to 'MyTable'". Am I doing something stupid? or is this a compiler's bug? Thanks!
(Using Xcode6-Beta5)
The reason why it does not work is there is no == operator defined for arrays with optional elements, only for non-optional elements:
/// Returns true if these arrays contain the same elements.
func ==<T : Equatable>(lhs: [T], rhs: [T]) -> Bool
You can provide your own:
func ==<T : Equatable>(lhs: [T?], rhs: [T?]) -> Bool {
if lhs.count != rhs.count {
return false
}
for index in 0..<lhs.count {
if lhs[index] != rhs[index] {
return false
}
}
return true
}
Another useful option is to use the elementsEqual:isEquivalent: method available on SequenceType. This could allow you to avoid implementing Equatable, but is best used rarely as it is more verbose.
Usage:
let a: [Int?] = []
let b: [Int?] = []
if a.elementsEqual(b, isEquivalent: { $0 == $1 }) {
print("foo") // Works
}

Declaring and using a bit field enum in Swift

How should bit fields be declared and used in Swift?
Declaring an enum like this does work, but trying to OR 2 values together fails to compile:
enum MyEnum: Int
{
case One = 0x01
case Two = 0x02
case Four = 0x04
case Eight = 0x08
}
// This works as expected
let m1: MyEnum = .One
// Compiler error: "Could not find an overload for '|' that accepts the supplied arguments"
let combined: MyEnum = MyEnum.One | MyEnum.Four
I looked at how Swift imports Foundation enum types, and it does so by defining a struct that conforms to the RawOptionSet protocol:
struct NSCalendarUnit : RawOptionSet {
init(_ value: UInt)
var value: UInt
static var CalendarUnitEra: NSCalendarUnit { get }
static var CalendarUnitYear: NSCalendarUnit { get }
// ...
}
And the RawOptionSet protocol is:
protocol RawOptionSet : LogicValue, Equatable {
class func fromMask(raw: Self.RawType) -> Self
}
However, there is no documentation on this protocol and I can't figure out how to implement it myself. Moreover, it's not clear if this is the official Swift way of implementing bit fields or if this is only how the Objective-C bridge represents them.
You can build a struct that conforms to the RawOptionSet protocol, and you'll be able to use it like the built-in enum type but with bitmask functionality as well. The answer here shows how:
Swift NS_OPTIONS-style bitmask enumerations.
Updated for Swift 2/3
Since swift 2, a new solution has been added as "raw option set" (see: Documentation), which is essentially the same as my original response, but using structs that allow arbitrary values.
This is the original question rewritten as an OptionSet:
struct MyOptions: OptionSet
{
let rawValue: UInt8
static let One = MyOptions(rawValue: 0x01)
static let Two = MyOptions(rawValue: 0x02)
static let Four = MyOptions(rawValue: 0x04)
static let Eight = MyOptions(rawValue: 0x08)
}
let m1 : MyOptions = .One
let combined : MyOptions = [MyOptions.One, MyOptions.Four]
Combining with new values can be done exactly as Set operations (thus the OptionSet part), .union, likewise:
m1.union(.Four).rawValue // Produces 5
Same as doing One | Four in its C-equivalent. As for One & Mask != 0, can be specified as a non-empty intersection
// Equivalent of A & B != 0
if !m1.intersection(combined).isEmpty
{
// m1 belongs is in combined
}
Weirdly enough, most of the C-style bitwise enums have been converted to their OptionSet equivalent on Swift 3, but Calendar.Compontents does away with a Set<Enum>:
let compontentKeys : Set<Calendar.Component> = [.day, .month, .year]
Whereas the original NSCalendarUnit was a bitwise enum. So both approaches are usable (thus the original response remains valid)
Original Response
I think the best thing to do, is to simply avoid the bitmask syntax until the Swift devs figure out a better way.
Most of the times, the problem can be solved using an enum and and a Set
enum Options
{
case A, B, C, D
}
var options = Set<Options>(arrayLiteral: .A, .D)
An and check (options & .A) could be defined as:
options.contains(.A)
Or for multiple "flags" could be:
options.isSupersetOf(Set<Options>(arrayLiteral: .A, .D))
Adding new flags (options |= .C):
options.insert(.C)
This also allows for using all the new stuff with enums: custom types, pattern matching with switch case, etc.
Of course, it doesn't have the efficiency of bitwise operations, nor it would be compatible with low level things (like sending bluetooth commands), but it's useful for UI elements that the overhead of the UI outweighs the cost of the Set operations.
They showed how to do this in one of the WWDC videos.
let combined = MyEnum.One.toRaw() | MyEnum.Four.toRaw()
Note that combined will be Int type and will actually get a compiler error if you specify let combined: MyEnum. That is because there is no enum value for 0x05 which is the result of the expression.
I think maybe some of the answers here are outdated with overcomplicated solutions? This works fine for me..
enum MyEnum: Int {
case One = 0
case Two = 1
case Three = 2
case Four = 4
case Five = 8
case Six = 16
}
let enumCombined = MyEnum.Five.rawValue | MyEnum.Six.rawValue
if enumCombined & MyEnum.Six.rawValue != 0 {
println("yay") // prints
}
if enumCombined & MyEnum.Five.rawValue != 0 {
println("yay again") // prints
}
if enumCombined & MyEnum.Two.rawValue != 0 {
println("shouldn't print") // doesn't print
}
If you don't need to interoperate with Objective-C and just want the syntax of bit masks in Swift, I've written a simple "library" called BitwiseOptions that can do this with regular Swift enumerations, e.g.:
enum Animal: BitwiseOptionsType {
case Chicken
case Cow
case Goat
static let allOptions = [.Chicken, .Cow, .Goat]
}
var animals = Animal.Chicken | Animal.Goat
animals ^= .Goat
if animals & .Chicken == .Chicken {
println("Chick-Fil-A!")
}
and so on. No actual bits are being flipped here. These are set operations on opaque values. You can find the gist here.
#Mattt's very famous "NSHipster" has an extensive detailed description of the RawOptionsSetType : http://nshipster.com/rawoptionsettype/
It includes a handy Xcode snipped:
struct <# Options #> : RawOptionSetType, BooleanType {
private var value: UInt = 0
init(_ value: UInt) { self.value = value }
var boolValue: Bool { return value != 0 }
static func fromMask(raw: UInt) -> <# Options #> { return self(raw) }
static func fromRaw(raw: UInt) -> <# Options #>? { return self(raw) }
func toRaw() -> UInt { return value }
static var allZeros: <# Options #> { return self(0) }
static func convertFromNilLiteral() -> <# Options #> { return self(0) }
static var None: <# Options #> { return self(0b0000) }
static var <# Option #>: <# Options #> { return self(0b0001) }
// ...
}
You have to use .toRaw() after each member:
let combined: Int = MyEnum.One.toRaw() | MyEnum.Four.toRaw()
will work. Because as it is you're just trying to assign "One" which is a MyEnum type, not an integer. As Apple's documentation says:
“Unlike C and Objective-C, Swift enumeration members are not assigned a default integer value when they are created. In the CompassPoints example, North, South, East and West do not implicitly equal 0, 1, 2 and 3. Instead, the different enumeration members are fully-fledged values in their own right, with an explicitly-defined type of CompassPoint.”
so you have to use raw values if you want the members to represent some other type, as described here:
Enumeration members can come prepopulated with default values (called raw values), which are all of the same type. The raw value for a particular enumeration member is always the same. Raw values can be strings, characters, or any of the integer or floating-point number types. Each raw value must be unique within its enumeration declaration. When integers are used for raw values, they auto-increment if no value is specified for some of the enumeration members. Access the raw value of an enumeration member with its toRaw method.
I use the following I need the both values I can get, rawValue for indexing arrays and value for flags.
enum MyEnum: Int {
case one
case two
case four
case eight
var value: UInt8 {
return UInt8(1 << self.rawValue)
}
}
let flags: UInt8 = MyEnum.one.value ^ MyEnum.eight.value
(flags & MyEnum.eight.value) > 0 // true
(flags & MyEnum.four.value) > 0 // false
(flags & MyEnum.two.value) > 0 // false
(flags & MyEnum.one.value) > 0 // true
MyEnum.eight.rawValue // 3
MyEnum.four.rawValue // 2
This worked for me.
1 << 0 //0000
1 << 1 //0010
1 << 2 //0100
1 << 3 //1000
enum Collision: Int {
case Enemy, Projectile, Debris, Ground
func bitmask() -> UInt32 {
return 1 << self.rawValue
}
}
I'm taking a guess that something like this is how they are modeling enum options in Foundation:
struct TestOptions: RawOptionSet {
// conform to RawOptionSet
static func fromMask(raw: UInt) -> TestOptions {
return TestOptions(raw)
}
// conform to LogicValue
func getLogicValue() -> Bool {
if contains([1, 2, 4], value) {
return true
}
return false
}
// conform to RawRepresentable
static func fromRaw(raw: UInt) -> TestOptions? {
if contains([1, 2, 4], raw) {
return TestOptions(raw)
}
return nil
}
func toRaw() -> UInt {
return value
}
// options and value
var value: UInt
init(_ value: UInt) {
self.value = value
}
static var OptionOne: TestOptions {
return TestOptions(1)
}
static var OptionTwo: TestOptions {
return TestOptions(2)
}
static var OptionThree: TestOptions {
return TestOptions(4)
}
}
let myOptions = TestOptions.OptionOne | TestOptions.OptionThree
println("myOptions: \(myOptions.toRaw())")
if (myOptions & TestOptions.OptionOne) {
println("OPTION ONE is in there")
} else {
println("nope, no ONE")
}
if (myOptions & TestOptions.OptionTwo) {
println("OPTION TWO is in there")
} else {
println("nope, no TWO")
}
if (myOptions & TestOptions.OptionThree) {
println("OPTION THREE is in there")
} else {
println("nope, no THREE")
}
let nextOptions = myOptions | TestOptions.OptionTwo
println("options: \(nextOptions.toRaw())")
if (nextOptions & TestOptions.OptionOne) {
println("OPTION ONE is in there")
} else {
println("nope, no ONE")
}
if (nextOptions & TestOptions.OptionTwo) {
println("OPTION TWO is in there")
} else {
println("nope, no TWO")
}
if (nextOptions & TestOptions.OptionThree) {
println("OPTION THREE is in there")
} else {
println("nope, no THREE")
}
...where myOptions and nextOptions are of type TestOptions - I'm not exactly sure how fromMask() and getLogicValue() are supposed to act here (I just took some best guesses), maybe somebody could pick this up and work it out?
If you want bitfield in Swift, then enum is the wrong way. Better just do like this
class MyBits {
static let One = 0x01
static let Two = 0x02
static let Four = 0x04
static let Eight = 0x08
}
let m1 = MyBits.One
let combined = MyBits.One | MyBits.Four
You don't really need the class/static wrapper, but I include it as a kind of pseudo namespace.
Do bitwise operation using raw value then create a new enum object using the result.
let mask = UIViewAutoresizing(rawValue: UIViewAutoresizing.FlexibleWidth.rawValue|UIViewAutoresizing.FlexibleHeight.rawValue)
self.view.autoresizingMask = mask
Here's something I put together to try to make a Swift enum that resembles to some extent a C# flags-style enum. But I'm just learning Swift, so this should only be considered to be "proof of concept" code.
/// This EnumBitFlags protocol can be applied to a Swift enum definition, providing a small amount
/// of compatibility with the flags-style enums available in C#.
///
/// The enum should be defined as based on UInt, and enum values should be defined that are powers
/// of two (1, 2, 4, 8, ...). The value zero, if defined, should only be used to indicate a lack of
/// data or an error situation.
///
/// Note that with C# the enum may contain a value that does not correspond to the defined enum
/// constants. This is not possible with Swift, it enforces that only valid values can be set.
public protocol EnumBitFlags : RawRepresentable, BitwiseOperations {
var rawValue : UInt { get } // This provided automatically by enum
static func createNew(_ rawValue : UInt) -> Self // Must be defined as some boiler-plate code
}
/// Extension methods for enums that implement the EnumBitFlags protocol.
public extension EnumBitFlags {
// Implement protocol BitwiseOperations. But note that some of these operators, especially ~,
// will almost certainly result in an invalid (nil) enum object, resulting in a crash.
public static func & (leftSide: Self, rightSide: Self) -> Self {
return self.createNew(leftSide.rawValue & rightSide.rawValue)
}
public static func | (leftSide: Self, rightSide: Self) -> Self {
return self.createNew(leftSide.rawValue | rightSide.rawValue)
}
public static func ^ (leftSide: Self, rightSide: Self) -> Self {
return self.createNew(leftSide.rawValue ^ rightSide.rawValue)
}
public static prefix func ~ (x: Self) -> Self {
return self.createNew(~x.rawValue)
}
public static var allZeros: Self {
get {
return self.createNew(0)
}
}
// Method hasFlag() for compatibility with C#
func hasFlag<T : EnumBitFlags>(_ flagToTest : T) -> Bool {
return (self.rawValue & flagToTest.rawValue) != 0
}
}
This shows how it can be used:
class TestEnumBitFlags {
// Flags-style enum specifying where to write the log messages
public enum LogDestination : UInt, EnumBitFlags {
case none = 0 // Error condition
case systemOutput = 0b01 // Logging messages written to system output file
case sdCard = 0b10 // Logging messages written to SD card (or similar storage)
case both = 0b11 // Both of the above options
// Implement EnumBitFlags protocol
public static func createNew(_ rawValue : UInt) -> LogDestination {
return LogDestination(rawValue: rawValue)!
}
}
private var _logDestination : LogDestination = .none
private var _anotherEnum : LogDestination = .none
func doTest() {
_logDestination = .systemOutput
assert(_logDestination.hasFlag(LogDestination.systemOutput))
assert(!_logDestination.hasFlag(LogDestination.sdCard))
_anotherEnum = _logDestination
assert(_logDestination == _anotherEnum)
_logDestination = .systemOutput | .sdCard
assert(_logDestination.hasFlag(LogDestination.systemOutput) &&
_logDestination.hasFlag(LogDestination.sdCard))
/* don't do this, it results in a crash
_logDestination = _logDestination & ~.systemOutput
assert(_logDestination == .sdCard)
*/
_logDestination = .sdCard
_logDestination |= .systemOutput
assert(_logDestination == .both)
}
}
Suggestions for improvement are welcome.
EDIT: I've given up on this technique myself, and therefore obviously can't recommend it anymore.
The big problem is that Swift demands that rawValue must match one of the defined enum values. This is OK if there are only 2 or 3 or maybe even 4 flag bits - just define all of the combination values in order to make Swift happy. But for 5 or more flag bits it becomes totally crazy.
I'll leave this posted in case someone finds it useful, or maybe as a warning of how NOT to do it.
My current solution to this situation is based on using a struct instead of enum, together with a protocol and some extension methods. This works much better. Maybe I'll post it someday when I'm more sure that that isn't also isn't going to backfire on me.
Task
Get all flags from flags_combination. Each flag and flags_combination are integers. flags_combination = flag_1 | flags_2
Details
Xcode 11.2.1 (11B500), Swift 5.1
Solution
import Foundation
protocol FlagPrototype: CaseIterable, RawRepresentable where RawValue == Int {}
extension FlagPrototype {
init?(rawValue: Int) {
for flag in Self.allCases where flag.rawValue == rawValue {
self = flag
return
}
return nil
}
static func all(from combination: Int) -> [Self] {
return Self.allCases.filter { return combination | $0.rawValue == combination }
}
}
Usage
enum Flag { case one, two, three }
extension Flag: FlagPrototype {
var rawValue: Int {
switch self {
case .one: return 0x1
case .two: return 0x2
case .three: return 0x4
}
}
}
var flags = Flag.two.rawValue | Flag.three.rawValue
let selectedFlags = Flag.all(from: flags)
print(selectedFlags)
if selectedFlags == [.two, .three] { print("two | three") }

Resources