Why can't I use an NSInteger in a switch statement? - iphone

Why doesn't this work:
NSInteger sectionLocation = 0;
NSInteger sectionTitles = 1;
NSInteger sectionNotifications = 2;
switch (section) {
case sectionLocation:
//
break;
case sectionTitles:
//
break;
case sectionNotifications:
//
break;
default:
//
}
I get this compile error:
error: case label does not reduce to an integer constant
Is it not possible to use NSInteger's like this? If so, is there another way to use variables as cases in a switch statement? sectionLocation etc. have variable values.

The problem isn't the scalar type, but that the case labels may change value when they are variables like that.
For all intents and purposes, the compiler compiles a switch statement as a set of gotos. The labels can't be variable.
Use an enumerated type or #defines.

The reason is that the compiler will often want to create a 'jump table' using the switch value as the key into that table and it can only do that if it's switching on a simple integer value. This should work instead:
#define sectionLocation 0
#define sectionTitles 1
#define sectionNotifications 2
int intSection = section;
switch (intSection) {
case sectionLocation:
//
break;
case sectionTitles:
//
break;
case sectionNotifications:
//
break;
default:
//
}

The problem here is you are using variables. You can only use constants in switch statements.
Do something like
#define SOME_VALUE 1
or
enum Values {
valuea = 1,
valueb = 2,
...
}
And you will be able to use valuea and so forth in your switch statement.

If your case values truly change at runtime, that's what the if...else if...else if construct is there for.

or just do this
switch((int)secion)

Related

Is there a way to access the unmatched value in a switch statement?

I want to access the value used in the switch statement in the default clause without first creating a temporary local var for the value, for example:
switch i + 5 {
case 2: // ...
case 7: // ...
default:
print("\(switchValue)")
}
Is there such a thing as, for example, a newValue in the didSet property clause?
You can conditionally bind to a variable, with no condition (so it acts like case _ or default
let i = 123
switch i + 5 {
case 2: break // ...
case 7: break // ...
case let switchValue:
print("\(switchValue)")
}
To be fair, you probably shouldn't do this.

Dart switch statement - Case expressions must be constant

I looked at a few questions regarding this for other languages and some suggest using final but that doesn't seem to work with Dart.
I'm passing in arguments so surely the switch statement cannot contain constants only? A switch statement, much like an if statement is asking if it is or not..ie it's unknown so I don't see how a switch statement can be useful if they have to be constants...?
setCategory(arga, argb) {
int result;
switch (true) {
case (arga >= 0 && arga < 3 && argb < 35):
result = 16;
break;
case (arga >= 0 && arga < 3 && argb >= 35):
result = 15;
break;
etc
It's returning the error Case expressions must be constant regarding the values arga and argb in the case expressions. What's the best way to remedy this or do I have to use an if statement?
The switch case expressions must be constants for sure.
You have to use if/then chains to do multiple tests based on non-constant values.
You cannot use arguments from the surrounding function in a switch case. What you are trying to do here is not supported by the Dart switch statement.
The Dart switch statement is deliberately kept very simple, so that a compiler can know all the possible cases at compile-time. That's why they must be compile-time constants.
Switch statements are still useful for some kinds of switching, like on enums:
enum Nonse { foo, bar, baz; }
String fooText(Nonse non) {
switch (non) {
case Nonse.foo: return "foo";
case Nonse.bar: return "bar";
case Nonse.baz: return "baz";
}
throw ArgumentError.notNull("non");
}
You can also switch over constant string values or integer values.
There are some rules for Switch Case
The default case is optional.
All case expression must be unique.
The case statements can include only constants. It cannot be a variable or an expression.
The data type of the variable and the case expression must match.
There can be any number of case statements within a switch.
you should use 'If Else' statement
Switch statement requires a constant -> it means already initialized variable with final value
switch (expression) {
case ONE : {
statement(s);
}
break;
case TWO: {
statement(s);
}
break;
default : {
statement(s);
}
}
for(int x=0; x<1; x++){
if(ing5<8 && toWhatDegreeRand<=10 && toWhatDegreeRand>7){
toWhatDegreeRand=9;
}
if(ing4<8 && toWhatDegreeRand<=7 && toWhatDegreeRand>5){
toWhatDegreeRand=6;
}
if(ing3<8 && toWhatDegreeRand<=5 && toWhatDegreeRand>3){
toWhatDegreeRand=4;
}//....
}
It can be a little useful.

Swift - Type 'int' does not conform to protocol 'intervaltype'

I found the following tutorial, which suggests the code after it should work. However, both cases throw type 'int' does not conform to protocol 'intervaltype' errors
Swift switch tutorial: http://www.codingexplorer.com/loops-switch-statements-ranges-swift/
let arrayCount = someArray?.count
switch arrayCount
{
case 0:
println("zero")
case 1:
println("one")
default:
println("etc")
}
The array is declared as an optional so its count is of type Optional(Int). It's necessary to check whether someArray is nil before using the count in a switch statement. Here is one way:
if let arrayCount = someArray?.count {
switch arrayCount {
case 0:
println("zero")
case 1:
println("one")
default:
println("etc")
}
}
If the array isn't nil the assignment will succeed and the if block will execute.
If you're certain the array isn't nil you can unwrap the optional using let arrayCount = someArray!.count instead of the conditional assignment.
Try this:
let arrayCount:Int = someArray?.count as Int
switch arrayCount
{
case 0:
println("zero")
case 1:
println("one")
default:
println("etc")
}
The problem is that arrayCount is of type Int?, so you should either implicitly unwrap it when you use switch on it:
switch arrayCount! { }
which is bad in case arrayCount is nil. Another option is that you could make sure arrayCount has a value by using coalescing operator, like this:
let arrayCount: Int = someArray?.count ?? 0
which would work in your code the way you tried to use it and also make sense for arrayCount to be 0.

Check if a objective c enum exists

I have predefined enum for buttons IDs:
typedef enum
{
button1ID = 407,
button2ID = 999,
button3ID = 408,
button4ID = 409,
} TOP_MENU_BUTTON_TYPE;
I need to find out if the ID I recieve is defiened in the enum. How can I do that? Something like:
if(id in TOP_MENU_BUTTON_TYPE)
There is no way to dynamically iterate an enum. Enums are static feature, they don't exist during runtime. In runtime they are just plain integers (of some size) and values.
It's not possible with this requirement you stated in bounty:
In your answer do not use hard coded values of the enum, just its type.
The other answers show you pretty much all ways to do it statically.
If I understand your question clearly, then this would be helpful to you..
Instead of using enum alone, you should try that with struct and here it is an answer by #Richard will help you how to do that.
Change enum values at runtime?
https://stackoverflow.com/a/10305425/1083859
In the above link, he explains how to use a dynamic enum values with struct and also you can iterate the values to find out. I think you will get an idea.
You can simply do this:
int validValue = button1ID | button2ID | button3ID | button4ID;
if (validValue & id)
// Valid enum value
An enum is not an object, it's just an integer that the compiler understands at build time. Because of this, you would need to provide low level code to make your check.
If you aren't pre-defining the values of your enums, they will start at 0 and increase by one. This lets you compare a value to see if it's <= your last element.
try this method:
-(BOOL)isDefined:(TOP_MENU_BUTTON_TYPE)type{
BOOL isDefined;
switch (type) {
case button1ID:
case button2ID:
case button3ID:
case button4ID:
isDefined = TRUE;
break;
default:
isDefined = FALSE;
break;
}
return isDefined;
}
//(...)
TOP_MENU_BUTTON_TYPE test;
test = 407;
NSLog(#"is %d a TOP_MENU_BUTTON_TYPE? result: %d", test, [self isDefined:test]);
test = 2;
NSLog(#"is %d a TOP_MENU_BUTTON_TYPE? result: %d", test, [self isDefined:test]);
so:
if ([self isDefined:test]){
// OK, test is defined in TOP_MENU_BUTTON_TYPE
}
in .h
typedef enum
{
407,
999,
408,
409,
} TOP_MENU_BUTTON_TYPE;
#interface CheckoutController : UIViewController{
TOP_MENU_BUTTON_TYPE type;
}
In .m
switch (status) {
case 407:
//Your Task
break;
case 999:
//Your Task
break;
case 408:
//Your Task
break;
case 409:
//Your Task
break;
}
Answers about using switch or bunch of || in if are correct, but…
If you have big enums (enum with a lot of values) you can make this simplier. Also Cocoa uses this trick.
Your enum values must be incremented by one.
Then add to enum two additional values:
typedef enum {
buttonIDMin = 407, // Lowest value
button1ID = 407,
button2ID = 408, // Incremented by ONE
button3ID = 409,
button4ID = 410,
buttonIDMax = 410, // Highest value
} TOP_MENU_BUTTON_TYPE;
When you are comparing, you just need to do:
if (buttonID >= buttonIDMin && buttonID <= buttonIDMax) ...

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.