How to compare switch statement control expression with its patterns in swift? - ios

I have a tried this and it does not work:
let value1 = 12
let sumOfOtherValues = 10 + 1 + 24
switch value1 {
case let (value1,sumOfOtherValues) where (value1 > sumOfOtherValues):
break;
case value1..>sumOfOtherValues:
break;
default:
breaK;
}
I would really like to make this in a switch statement and not in an if statement.

is this what you need? (I don't understand your need for value1..>sumOfOtherValues
let value1 = 12
let sumOfOtherValues = 10 + 1 + 24
switch value1 {
case _ where sumOfOtherValues > value1:
println("case 1")
//break //it's not mandatory.
fallthrough //Without this code, this will stop here if the switch match this case. If you want that your switch continue to search, add 'fallthrough' at the end of each case
case _ where value1 > sumOfOtherValues:
println("case 2")
break
default:
break
}

Related

Switch case warning in swift

I have switch condition on Int32 attribute of core-data entity as
switch location.userLocationLike?.likeStatusId {
case 1 as Int32:
view.lblLike.text = "LIKED"
case 2 as Int32:
view.lblLike.text = "OKAY"
case 3 as Int32:
view.lblLike.text = "DISLIKE"
default:
view.lblLike.text = "LIKE"
}
If I don't type cast value as Int32 than it shows error, And if I convert it to Int32 than warning. Can anyone please explain me what is the best way to write Switch-case.
The error is misleading, you cannot switch on an optional with non-optional cases, optional bind (or even forced unwrap) userLocationLike, according to the warnings the as Int32 casts are meaningless.
if let likeStatus = location.userLocationLike {
switch likeStatus.likeStatusId {
case 1: view.lblLike.text = "LIKED"
case 2: view.lblLike.text = "OKAY"
case 3 view.lblLike.text = "DISLIKE"
default: view.lblLike.text = "LIKE"
}
}

Exit from loop after finding the first positive element in swift

So, need you help, I have loops, where I'd like to find first positive element and it will be text of label and exit from all loops, but every time I get last element:
for j in getArrayOfAllTimes[i].timeForGetDifference()
{
switch j - timeNow() {
case let x where x > 0:
nextTimeLabel.text = String(j - timeNow())
break
default:
break
}
}
How get first element > 0?
The first(where:) method of Array
Instead of explicitly breaking out of a loop when a first element that fulfills som predicate is found, you could simply make use of the Array method first(where:).
Since you haven't provided us with a minimal, complete and verifiable example (which you should) we'll construct such an example:
/* Example setup */
struct Foo: CustomStringConvertible {
private let bar: Int
init(_ bar: Int) { self.bar = bar }
func timeForGetDifference() -> Int {
return bar
}
var description: String {
return String(bar)
}
}
func timeNow() -> Int { return 10 }
let getArrayOfAllTimes = [Foo(6), Foo(2), Foo(9), Foo(4), Foo(11), Foo(3), Foo(13)]
// nextTimeLabel: some UILabel
For the example as per above, we could set the text property of the nextTimeLabel as follows, using first(where:) to find the first element fulfilling our predicate, given that it exists (otherwise; will return nil in which case we will not enter the optional binding block below).
if let firstNonNegativeFoo = getArrayOfAllTimes
.first(where: { $0.timeForGetDifference() - timeNow() > 0 }) {
nextTimeLabel.text = String(describing: firstNonNegativeFoo) // 11
}
As to why your own approach does not work as intended: a break statement within a case of a switch statement will simply end the execution of the switch statement (not the loop which is one level above the switch statement.
From the Language Reference - Statements:
Break Statement
A break statement ends program execution of a loop, an if statement,
or a switch statement.
In you case, you've added the break statements as the last statements of each case: here, particularly, the break has truly no effect (since the switch statement would break out anyway, after exiting the case which it entered).
for i in 1...3 {
switch i {
case is Int: print(i); break // redundant 'break'
case _: ()
}
} // 1 2 3
// ... the same
for i in 1...3 {
switch i {
case is Int: print(i)
case _: ()
}
} // 1 2 3
for j in getArrayOfAllTimes[i].timeForGetDifference() {
bool a = NO;
switch j - timeNow() {
case let x where x > 0:
a = YES
nextTimeLabel.text = String(j - timeNow())
break
default:
break
}
if a == YES {
break;
}
}

How to make switch statement with optionals?

I'm working with text fields and json data. I want to test if the json data is != nil, if it is, then I fill it's field with that info, if it's == nil then I put a placeholder in its field instead. Like this:
if memberInfo?.createDate != nil {
self.activeSinceTextField.text = stringToDateToString((memberInfo?.createDate)!)
} else {
placeHolder("Enter Here".localized())
self.activeSinceTextField.attributedPlaceholder = placeHolderText
}
if memberInfo?.birthDate != nil
{self.birthdayTextField.text = stringToDateToString((memberInfo?.birthDate)!)
} else
{ placeHolder("Enter Here".localized())
self.birthdayTextField.attributedPlaceholder = placeHolderText
}
I have a lot of fields and I'm thinking a switch statement would make this a lot cleaner. I'm just not sure how to make one for this type of situation.
Version 1
This is how you define the 4 outcomes with a switch
switch (memberInfo?.createDate, memberInfo?.birthDate) {
case (.Some, .Some): break
case (.Some, nil): break
case (nil, .Some): break
case (nil, nil): break
}
Now just replace the break(s) with the code you want to execute for each scenario.
Version 2
Here you have createDate and/or birthDate unwrapped when available
switch (memberInfo?.createDate, memberInfo?.birthDate) {
case (let .Some(createDate), let .Some(birthDate)):
print(createDate, birthDate)
case (let .Some(createDate), .None):
print(createDate)
case (.None, let .Some(birthDate)):
print(birthDate)
case (.None, .None):
print("Both are nils")
}
Legend
.Some: means here there is something
.None: means this is nil
_: means is a jolly, it means I don't care what there is here

Initialized enum returns wrong hashValue

This is Swift 1.2 and I'm using Xcode 6.4. The following enum has a failable initializer.
enum EstimateItemStatus: Int, Printable {
case Pending = 1
case OnHold = 2
case Done = 3
var description: String {
switch self {
case .Pending: return "Pending"
case .OnHold: return "On Hold"
case .Done: return "Done"
}
}
init?(id : Int) {
switch id {
case 1:
self = .Pending
case 2:
self = .OnHold
case 3:
self = .Done
default:
return nil
}
}
}
If I pass an ID and initialize an instance, the enum value I get is correct. However the hashValue is wrong. For example,
let status = EstimateItemStatus(id: 2)!
println("\(status.hashValue) - \(status)")
The output I get is 1 - On Hold.
But it should be 2 - On Hold.
What am I doing wrong here? Is this a compiler bug or am I missing something?
Demo playground
Maybe you're mixing up hashValue vs. rawValue.
The hash value is not enforced to be equal to the raw value

Reduced form for using an OR operator?

Is there a way to make this statement shorter?
let number = 1
if number == 0 || number == 1 {
print("ok")
}
like
let number = 1
if number == (0 || 1) {
print("ok")
}
This one doesn't work but I was wondering if there is a shorter way that I am not aware of.
EDIT:
I am aware of the switch case that might be useful when many case appear, but in my case I was more looking for something to use with ternary operators:
let oldNumber = 1
let newNumber = (oldNumber = 0 || 1) ? 4 : 13
Boolean equation expressions are evaluated always providing left (number) and right (0) side.
Not really shorter but you could write
let number = 1
if (0...1).contains(number) {
print("ok")
}
just for variety:
let c = { (number:Int, args:Int...) -> Bool in return args.contains(number) }
let number = 1;
if c(number, 0,1,9,4) {
print("ok")
}
only shorter if you are going to reuse the closure, has the advantage over the 0...1 range because you can specify a disjoint set of numbers. Can be used for inline if statements etc quite neatly
Little poor but nevertheless.
let number = 1
print((0...1).contains(number) ? "ok" : "bad")
Or:
let a = 1
let b = (0...1).contains(a) ? 4 : 5
When checking for several possible cases the switch statement might be more concise.
let number = 1
switch (number) {
case 0, 1:
print("ok")
default:
print("something else")
}

Resources