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

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;
}
}

Related

Can I get the number of a case statement in 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];
}

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];

Odd compiler error when using Obj-C objects in a switch statement

I get a compiler error when using an Objective-C object within a switch statement:
switch (myConstant)
{
case 0:
UIViewController *myController = [[[UIViewController alloc] init] autorelease];
[self.navigationController pushViewController:myViewController animated:YES];
break;
case 1:
// stuff
break;
default:
break;
}
The error states:
Expected expression before 'UIViewController'
'myViewController' undeclared (first use in this function)
I understand that the second error is a direct result of the first error, but what I don't understand is why I get the 'expected expression' error in the first place...
If I put a ; at the end of the case 0: line, then it will compile, but I shouldn't have to do this, no?
This will also fail to compile, with the same error:
switch (0)
{
case 0:
int a = 0;
break;
default:
break;
}
However, if I declare the int a; outside of the switch block, then a = 0; compiles fine.
I thought I understood switch statements - clearly I don't. Could someone please explain?
Just add {} within the case if you declare a new variable. The case part of a switch statement is not a correct scope to declare variables in C.
case 0:
{
int a = 0;
break;
}
...