Compile Error with: switch, "expected expression before" - iphone

Cut to the chase I have recreated my problem as it is fairly self explanatory.
this complies without error:
switch (n) {
case 1:
NSLog(#"");
NSString *aStr;
break;
default:
break;
}
this compiles with error and it's only missing the NSLog():
switch (n) {
case 1:
NSString *aStr;
break;
default:
break;
}
it throws an error at compile "Expected expression before 'NSString'"
Am I missing something here?

In normal C you'd have to enclose this in brackets in both cases. I suspect this may fix your problem:
case 1:
{
NSLog(#"");
NSString *aStr;
break;
}
See this SO question for more info.
Another way to get around this problem is to put a statement between the case label and the first declaration as you've done in your working example above. See the comments and Quinn Taylor's answer for more info.

You can't declare a variable as the first statement in a case without brackets, and in many other contexts in C-based languages. See Declaring variables inside a switch statement for details.

case 0: {
Loading my nib file;
break;
}
case 1: {
Loading another nib file;
break;
}
Note that if you don't have an assignment (x = y) right after the case it won't be a problem. For example:

Related

Empty cases in Swift

What is the difference between line A and line B:
let a = 1
switch a {
case 1:
break;//line A
case 2:
print("2")
default:
()//line B
}
My guess is that break is saying leave the switch, whereas () is saying do nothing.
I'm not sure what to search for this, and I'm new to Swift, so links are appreciated
In your example, there is no difference. They are both placeholders. The rule is that a case cannot be completely empty. Both are acting as ways of meeting that requirement.

Pass Keyword in Swift

I know that the keyword "pass" in Python will allow one to leave a line of code empty where it should have contained an executable statement. Is there a similar keyword in Swift?
I am using a switch statement and Swift requires there to be a default case. The code should reach the default statement most of the time and I want nothing to be done in this case.
You can break out of the default case. Swift just wants you to be explicit about that to avoid bugs.
Here's a simple example:
enum Food {
case Banana
case Apple
case ChocolateBar
}
func warnIfUnhealthy(food : Food) {
switch food {
case .ChocolateBar:
println("Don't eat it!")
default:
break
}
}
let candy = Food.ChocolateBar
warnIfUnhealthy(candy)
The proper way to add a catch-all without an action to a switch statement is to add
default: break
at the end.

Noop for Swift's Exhaustive Switch Statements

Swift requires exhaustive switch statements, and that each case have executable code.
'case' label in a 'switch' should have at least one executable statement
Has anybody settled on a good way to handle the cases where you don't want to actually do anything? I can put a println() in there, but that feels dirty.
According to the book, you need to use break there:
The scope of each case can’t be empty. As a result, you must include at least one statement following the colon (:) of each case label. Use a single break statement if you don’t intend to execute any code in the body of a matched case.
You can use a break statement:
let vegetable = "red pepper"
var vegetableComment: String = "Nothing"
switch vegetable {
case "cucumber", "watercress":
break // does nothing
case let x where x.hasSuffix("pepper"):
vegetableComment = "Is it a spicy \(x)?"
default:
vegetableComment = "Everything tastes good in soup."
}
Example modified from the docs
Below is one option for null statement, but maybe not a good solution. I cannot find a statement like python pass
{}()
for switch case, break is better choice.
break
Do nothing in exhaustive switch case statements:
Swift:
switch yourVariable {
case .someCase:
break
}
SwiftUI:
switch yourVariable {
case .someCase:
EmptyView() // break does not work with ViewBuilder
}
Using EmptyView() instead of break in SwiftUI views prevents the error:
Closure containing control flow statement cannot be used with function
builder ViewBuilder.
EmptyView() is a SwiftUI standard view (tested with Xcode 12, iOS 14) and does not need to be defined yourself.
In addition to break mentioned in other answers, I have also seen () used as a no-op statement:
switch 0 == 1 {
case true:
break
case false:
()
}
Use () if you find break confusing or want to save 3 characters.
The cleanest solution I've found is to simply include your last statement in the switch case as your default. This avoids the need to add break or other unnecessary statements while still covering all possible cases.
For example:
switch myVar {
case 0:
myOtherVar = "Red"
case 1:
myOtherVar = "Blue"
default:
myOtherVar = "Green"
}
You can check specific case, no need to be exhustive with switch cases
Say you have a enum like this,
enum Selection {
case one
case two
case three
}
var myCase = Selection.one
you can check like this,
if case .one = myCase {
print("one")
}
A clean solution I use for my default case is:
default: ()

Can I make a switch([NSNull null])? (Objc)

I have a rather simple question and forgive me if it is sacrilege to ask it haha.
I have 6 variables that I need to test if they are null or if their length is 0. So I figured that maybe I could use two switches, one for testing if it is string == [NSNull null] and one for testing string.length == 0. Instead of making a huge and complicated if.
A switch such as:
switch([NSNull null])
{
case string:
Do something
break;
case string2:
Do something else
break;
// etc...
}
and then another one such as:
switch( length==0) //I know length==0 doesn't work, but maybe you know an alternative
{
case string:
Do something
break;
case string2:
Do something else
break;
// etc...
}
Thank you for your help!
For your first switch statement, you can't an object within your switch brackets (an instance of NSNull is returned [NSNull null]). You must use primitives within the bracket only. Furthermore, your throught process is clearly flawed, as [NSNull null] will always return the same sort of object (an object that represents a null value), and therefore you have nothing to switch on, as opposed to switching on an integer, whereby your case statements could be for different integers.
For your second switch statement, you cannot (again) use objects for your cases (NSString is, of course, an object). The best thing to do here would be to use a series of if else clauses as follows:
if ([string length] == 0)
{
if ([string isEqualTo:#"firstStringToCheck"])
{
// Do something.
}
else if ([string isEqualTo:#"secondStringToCheck"])
{
// Do something else.
}
}
Notice that I also use the instance method named length in order to get the length of the string and check that it is 0. This seems to be what you were trying to do in your example, but also makes absolutely no sense to me. Why would you want to check strings with other strings when you know that if the string's length is 0 it couldn't possibly match any strings!
You're totally misunderstanding how the switch statement works. It's designed to test multiple possible variables for a set of possible values. Specifically to replace code like:
if (value == 0)
NSLog (#"zero");
else if (value == 1)
NSLog (#"one");
else if (value == 2)
NSLog (#"two");
else if (value == 3)
NSLog (#"three");
else if (value == 4)
NSLog (#"four");
else if (value == 5)
NSLog (#"five");
else
NSLog (#"Integer out of range");
with
switch (value)
{
case 0:
NSLog (#"zero");
break;
case 1:
NSLog (#"one");
break;
case 2:
NSLog (#"two");
break;
case 3:
NSLog (#"three");
break;
case 4:
NSLog (#"four");
break;
case 5:
NSLog (#"five");
default:
NSLog (#"Integer out of range");
break;
}
what you're currently doing will give you unexpected results. Use an if statement, or write a function to handle testing for null. See enter link description here, where I shamelessly cribbed these examples from for more information.

why switch will expect statement before loading nib

In Switch statement
Example
switch (indexPath.row)
case 0:
Loading my nib file;
break;
case 1:
Loading another nib file;
break
default:
break
........
Before loading my nib file. It expects any one statement.
example
case 0:
NSLog(#"");
Loading Nib file....
My its expect the statement NSLog(#"");....... If i need not put NSLog... or any other statement its gives me error.....
I want to know why its like that.
It's a problem that Objective-C inherited from C in a strange way. Basically the statements in each case have to be in a single block. The compiler figures this out when the statement immediately after the case statement isn't an assignment, but gets confused if it is.
You can solve it the way you did, with the NSLog, or you can simply surround your statements with curly braces to create a block:
case 0: {
Loading my nib file;
break;
}
case 1: {
Loading another nib file;
break;
}
Note that if you don't have an assignment (x = y) right after the case it won't be a problem. For example:
case 0:
if (a = 1) NSLog(#"This works fine");
break;
In the later example you gave you instantiated an object right after the case statement -- TestiPhoneCalViewController *testiPhoneCalViewController -- which wasn't an assignment, so it was fine.