Can I get the number of a case statement in Objective-C? - objective-c

I have a switch statement like this:
switch (int) {
case 0:
// do x
break;
case 1:
// do y
break;
default:
break;
}
Can I get the case number?
The reason I ask is that I have a method in each one that would use a variable int. For example:
switch (int) {
case 0:
[self doMethod:string setTag: <CASE NUMBER> ];
break;
case 1:
[self doMethod:string setTag: <CASE NUMBER> ];
break;
default:
break;
}
Is there any way to do this?
Thanks!

switch (x) {
case 0:
// if you're here, you know x == 0
[self doMethod:string setTag: x];
break;
...
}
But unless string is a different variable or literal in each case, this doesn't make much sense; you could as easily say
if (x == 0 || x == 1) {
[self doMethod: string setTag: x];
}

First off, you can't do switch (int). int is a data type. You need a variable in there.
Then all you need to do is reference the variable in the case statement:
int someVar = ... // some value
switch (someVar) {
case 0:
[self doMethod:string setTag:someVar];
break;
case 1:
[self doMethod:string setTag:someVar];
break;
}
BTW - if you do the same thing for multiple cases you can do:
int someVar = ... // some value
switch (someVar) {
case 0:
case 1:
[self doMethod:string setTag:someVar];
break;
default:
// other stuff
break;
}
And as Josh pointed out, depending on your needs, this whole thing could simply be:
int someVar = ... // some value
[self doMethod:string setTag:someVar];
or maybe:
int someVar = ... // some value
if (someVar >= 0 && someVar <= 1) {
[self doMethod:string setTag:someVar];
}

Related

Section's and cases

A small issue over here i have 4 sections when i click on the first TableCell of a section (got 4 sections) the NSlogs output is:
2012-02-20 20:33:16.870 [8880:c07] 00
Can i do something like;
if switch(indexPath.row == 0) {
case
} else if(indexPath.row == 1) {
case
}
to 'link' each Tablecell to another function?
The problem is when i use the code ;
case 0:
NSLog(#"00");
break;
each first Tablecell of a section gives me the NSlog 00
UIViewController *controller;
switch(indexPath.row) {
case 0:
NSLog(#"00");
break;
case 1:
NSLog(#"01");
break;
case 2:
NSLog(#"02");
break;
case 3:
NSLog(#"03");
break;
case 4:
NSLog(#"04");
break;
}
I think you are looking for something like this:
if (indexPath.section == 0) {
switch(indexPath.row) {
case 0:
NSLog(#"00");
break;
case 1:
NSLog(#"01");
break;
case 2:
NSLog(#"02");
break;
case 3:
NSLog(#"03");
break;
case 4:
NSLog(#"04");
break;
}
} else if (indexPath.section == 1) {
switch(indexPath.row) {
case 0:
NSLog(#"10");
break;
case 1:
NSLog(#"11");
break;
case 2:
NSLog(#"12");
break;
case 3:
NSLog(#"13");
break;
case 4:
NSLog(#"14");
break;
}
}
The if statement separates the execution path on the section, and then switch further separates it on the row. If the number of sections is significant, you could use an outer switch outside of the inner switches.

Adding a decimal point button to an iOS Calculator

I followed a tutorial to make an iOS Calculator, and I am now wanting to add a decimal place button to it. Here is my code
header file:
#import <UIKit/UIKit.h>
#interface CalcViewController : UIViewController {
float result;
float selectedNumber;
int selectedOperation;
IBOutlet UILabel *calcScreen;
}
-(IBAction)numberPressed:(id)sender;
-(IBAction)operationPressed:(id)sender;
-(IBAction)clearNumber:(id)sender;
-(IBAction)clearOperation:(id)sender;
#end
Here is my implementation file
#import "CalcViewController.h"
#implementation CalcViewController
-(IBAction)numberPressed:(id)sender {
selectedNumber = selectedNumber * 10 + (float) [sender tag];
calcScreen.text = [NSString stringWithFormat:#"%2g", selectedNumber];
}
-(IBAction)operationPressed:(id)sender {
if (selectedOperation == 0) {
result = selectedNumber;
} else {
switch (selectedOperation) {
case 1:
result = result + selectedNumber;
break;
case 2:
result = result - selectedNumber;
break;
case 3:
result = result * selectedNumber;
break;
case 4:
result = result / selectedNumber;
break;
case 5:
selectedOperation = 0;
break;
}
}
selectedNumber = 0;
calcScreen.text = [NSString stringWithFormat:#"%2g", result];
if ([sender tag] == 0) result = 0;
selectedOperation = [sender tag];
}
-(IBAction)clearNumber:(id)sender {
selectedNumber = 0;
calcScreen.text = #"0";
}
-(IBAction)clearOperation:(id)sender {
selectedNumber = 0;
calcScreen.text = #"0";
selectedOperation = 0;
}
I saw on another thread that someone had suggesting using the method:
- (IBAction)Decimal:(id)sender
{
NSString *currentText = calcScreen.text;
if ([currentText rangeOfString:#"." options:NSBackwardsSearch].length == 0) {
calcScreen.text = [calcScreen.text stringByAppendingString:#"."];
}
However this did not seem to work for me. It would indeed let me enter a decimal point, but when a second number was entered the decimal point would be lost. Can anyone suggest a method I could implement to achieve what I am trying to?
Cheers in advance!
My quick thought: keep the number as text on the screen, adding additional digits and/or decimal point to it as text. Only convert it to a float (I would use double myself, btw) at the moment that an operation is performed. The suggested method should then work fine.
Something like:
-(IBAction)numberPressed:(id)sender {
calcScreen.text = [calcScreen.text stringByAppendingString:[sender tag]];
}
-(IBAction)operationPressed:(id)sender {
selectedNumber = [calcScreen.text floatValue];
...
}
One quick tip, instead of using
int selectedOperation;... and later in code
switch (selectedOperation) {
case 1:
result = result + selectedNumber;
break;
case 2:
result = result - selectedNumber;
...
Try using typedef enum
typedef enum {
OperationTypeAdd = 0,
OperationTypeSub,
...
} OperationType
and in switch block
switch (operationType) {
case OperationTypeAdd:
result = result + selectedNumber;
break;
case operationTypeSub:
result = result - selectedNumber;
break;

Switch with typedef enum type from string

I used the typedef enum below but the switch always return the default case why ?
typedef enum {
first,
LatestNews,
Opinion,
Special,
Sports,
Thisweek,
} NAChannelTitle;
-(NSString *)getImageName:(NSString *)channelName {
NAChannelTitle temp = (NAChannelTitle)[channelName stringByReplacingOccurrencesOfString:#" " withString:#""];
NSLog(#"Temp : %#",temp);
switch (temp) {
case first:
return #"background-channel-sporttitle-portrait.png";
break;
case LatestNews:
return #"background-channel-title-portrait.png";
break;
case Opinion:
return #"background-channel-title-portrait.png";
break;
case Special:
return #"background-channel-sporttitle-portrait.png";
break;
case Sports:
return #"background-channel-sporttitle-portrait.png";
break;
case Thisweek:
default:
return #"background-channel-title-portrait.png";
break;
}
return nil;
}
You can't convert a string to enum, since the enums names are not saved, instead, you can create a function that does it, by comparing strings, this is longer, but I don't think you have other option. a macro may help:
NAChannelTitle getEnumTitle(NSString *sTitle) {
#define CHECK_ENUM(X) if([sTitle isEqualToString:##X]) return X
CHECK_ENUM(first);
// the same for all enum
return defaultEnum; // add this to the enum
#undef CHECK_ENUM
}
then you may do:
NAChannelTitle temp = getEnumTitle(channelName);
NSLog(#"Temp : %d",temp);
switch (temp) {
case first:
return #"background-channel-sporttitle-portrait.png";
break;
case LatestNews:
return #"background-channel-title-portrait.png";
break;
case Opinion:
return #"background-channel-title-portrait.png";
break;
case Special:
return #"background-channel-sporttitle-portrait.png";
break;
case Sports:
return #"background-channel-sporttitle-portrait.png";
break;
case Thisweek:
default:
return #"background-channel-title-portrait.png";
break;
}
return nil;
This is what ppl looking for . Here is the shortest answer without any string comparison:
// Zoey.h
typedef enum {
turnLeft,
turnRight,
turnTop,
turnBottom
} arrowType;
// Zoey.m
NSString * const arrowTypeTypeArray[] = {
#"turnLeft",
#"turnRight",
#"turnTop",
#"turnBottom"
};
// A method to convert an enum to string.is it short enuff eh ?
-(NSString*) arrowTypeEnumToString:(arrowType)enumVal
{
return arrowTypeArray[enumVal];
}
// An extra method to retrieve the int value from the C array of NSStrings
-(arrowType) arrowTypeStringToEnum:(NSString*)strVal
{
int retVal;
for(int i=0; i < sizeof(arrowTypeArray)-1; i++)
{
if([(NSString*)arrowTypeArray[i] isEqual:strVal])
{
retVal = i;
break;
}
}
return (arrowType)retVal;
}
You're converting a string to an enum, this doesn't work. Strings are pointers, enums are numbers, and even though you can cast them, a pointer won't have the same value.
You'll need something like:
if([temp isEqualToString:#"LatestNews"]){ ... }
and so on. Or some method to convert to an enum, which you can then switch on.
Also those break statements are useless
The enum, stands for enumeration - you are just creating names for some integers.
typedef enum {
first,
LatestNews,
Opinion,
Special,
Sports,
Thisweek,
} NAChannelTitle;
means that first is 0, LatestNews is 1, and so on.
In your function you are casting a NSString to NSInteger - hence you are not getting correct values.
You need to use the [string isEqualToString:] method to compare your string to some conditional values.
Enumeration declaration explained

Strange Switch Parse error

switch (indexPath.section) {
case 0: //products used
NSString * chemical = [selectedChemicals objectAtIndex:indexPath.row];
cell.textLabel.text = chemical;
break;
case 1: //areas sprayed
return [selectedAreas count];
break;
case 2://target pests
return [selectedPests count];
break;
case 3://notes
return 1;
break;
}
gives me: "/Users/grady/programming/ObjectivelyBetter/bioguard/Classes/JobWizardViewController.m:147: error: 'chemical' undeclared (first use in this function)"
putting a blank semi-colon at the beginning of the case fixes it.
switch (indexPath.section) {
case 0: //products used
;
NSString * chemical = [selectedChemicals objectAtIndex:indexPath.row];
cell.textLabel.text = chemical;
break;
case 1: //areas sprayed
return [selectedAreas count];
break;
case 2://target pests
return [selectedPests count];
break;
case 3://notes
return 1;
break;
}
When you declare variables within a case statement, it's a good practice (and required to avoid these kinds of errors) to enclose the statements inside curly braces, e.g.
case 0:
{
int i = 0;
....
break;
}
Not sure why a semicolon along would have "solved" the issue. That's kind of odd... the curly braces are what you need.
In your particular case you could also just eliminate the local variable declaration and set the cell textLabel like so:
cell.textLabel.text = [selectedChemicals objectAtIndex:indexPath.row];

Why can't I create an variable in an switch block?

Strange:
switch(type) {
case NSFetchedResultsChangeInsert:
int x = 5; // error: "Expected expression before int"
break;
}
So it isn't possible to create a local variable in an switch-case-block?
Did you try adding curly braces?
switch(type) {
case NSFetchedResultsChangeInsert:
{
int x = 5; // error: "Expected expression before int"
break;
}
}