Strange Switch Parse error - objective-c

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

Related

Objective-C A switch statement inside another switch statement

So I have created a switch statement inside another switch statement for certain sections and rows, quite hard to explain so have a look at the actual code. Anyways I was wondering if such patter should be avoided or if it does not really matter, I am new to stackoverflow as you may have already noticed so I am not entirely sure this question has been asked before.
switch(indexPath.section) {
case 0: {
switch ([indexPath row]) {
case 0: {
[self.navigationController pushViewController:introductionViewController animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
break;
}
case 1: {
[self.navigationController pushViewController:matterViewController animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
break;
}
break;
}
case 1: {
break;
}
}
}
A switch statement inside of a switch statement is perfectly legal. There's nothing inherently wrong with it, though it may be difficult to follow if there are many cases in either statement. One solution is to make the inner switch statement into a separate function or method. For example, if you have this:
switch (a)
{
case foo:
switch (b)
{
case bar:
doSomething();
break;
case bas:
doSomethingElse();
break;
}
break;
case foo2:
...whatever
}
You could do it like this:
void handleFoo (int x)
{
switch (x)
{
case bar:
doSomething();
break;
case bas:
doSomethingElse();
break;
}
}
...
main ()
{
...
switch (a)
{
case foo:
handleFoo(b);
break;
case foo2:
...whatever;
break;
}
}

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

How to add a buttons to a MutableArray according to their tag number in objective-C?

i have a view contains many sections(group of buttons) each section in the view contains unique id, i want to add buttons to an NSMutableArray according to their id,(i.e. when the user clicks a button i get the button id then add to the array all the buttons have that id) i wrote these code, but when i check the length of the array after adding i found it to be 0 !!
Hint: sec_0,sec_1,sec_2,sec_3,sec_4,sec_5,sec_6,sec_7,sec_8 is a predifined NSMUtable arrays.
-(NSMutableArray*)findButtonsSection:(UIButton *)buton{
NSLog(#"Inside findButtonsSection");
int tag_No=buton.tag;
for (UIButton* bton in self.view.subviews) {
NSLog(#"Inside findButtonsSection2");
switch (tag_No) {
case 0:
[sec_0 addObject:bton];
NSLog(#"Number of buttons in array=%i",[sec_0 count]);
break;
case 1:
NSLog(#"Button tag No=%i",buton.tag);
[sec_1 addObject:bton];
return sec_1;
break;
case 2:
NSLog(#"Button tag No=%i",buton.tag);
[sec_2 addObject:bton];
return sec_2;
break;
case 3:
NSLog(#"Button tag No=%i",buton.tag);
[sec_3 addObject:bton];
return sec_3;
break;
case 4:
NSLog(#"Button tag No=%i",buton.tag);
[sec_4 addObject:bton];
return sec_4;
break;
case 5:
NSLog(#"Button tag No=%i",buton.tag);
[sec_5 addObject:bton];
return sec_5;
break;
case 6:
NSLog(#"Button tag No=%i",buton.tag);
[sec_6 addObject:buton];
return sec_6;
break;
case 7:
NSLog(#"Button tag No=%i",buton.tag);
[sec_7 addObject:bton];
return sec_7;
break;
case 8:
NSLog(#"Button tag No=%i",buton.tag);
[sec_8 addObject:bton];
return sec_8;
break;
default:
NSLog(#"nnnnnnnnnn");
}
}
}
Form a C array out of those sec_x mutable arrays after they're constructed. Like this:
NSMutableArray *secs[] = {sec_0, sec_1....};
Then use indexing instead of switch:
[secs[tag_No] addObject:bton];
The square brackets in this case denote array element access, not an Objective C method call.
On a more general note, read up on plain old C. The Objective C/iOS tutorials often assume, without spelling it out, that you have some C background and start by explaining the Objective C object system rather than the C bits.
The reason your arrays are all empty is because you return after you add any value to an array that isnt sec_0. You don't want those returns, as it will break out of your for loop. Try the code below:
You could also switch the array around to save you some lines of code and improve readibility.
-(NSMutableArray *)findButtonSelections:(UIButton *)button {
NSArray *array = [NSArray arrayWithObjects:sec_0, sec_1, sec_2, sec_3, sec_4, sec_5, sec_6, sec_7, sec_8, nil];
int tag = button.tag;
//BTW, this function will return all views, not just buttons
for (UIButton* bton in self.view.subviews) {
//So add this to make sure the view is a button
if([bton isKindOfClass:[UIButton class]]) {
[[array objectAtIndex:tag] addObject:bton];
}
}
return [array objectAtIndex:tag];
}
If you wanted to keep your switch code, try this below, but i don't recommend it.
-(NSMutableArray *)findButtonSelections:(UIButton *)button {
NSLog(#"Inside findButtonsSection");
int tag_No=buton.tag;
for (UIButton* bton in self.view.subviews) {
NSLog(#"Inside findButtonsSection2");
switch (tag_No) {
case 0:
[sec_0 addObject:bton];
NSLog(#"Number of buttons in array=%i",[sec_0 count]);
break;
case 1:
NSLog(#"Button tag No=%i",buton.tag);
[sec_1 addObject:bton];
break;
case 2:
NSLog(#"Button tag No=%i",buton.tag);
[sec_2 addObject:bton];
break;
case 3:
NSLog(#"Button tag No=%i",buton.tag);
[sec_3 addObject:bton];
break;
case 4:
NSLog(#"Button tag No=%i",buton.tag);
[sec_4 addObject:bton];
break;
case 5:
NSLog(#"Button tag No=%i",buton.tag);
[sec_5 addObject:bton];
break;
case 6:
NSLog(#"Button tag No=%i",buton.tag);
[sec_6 addObject:buton];
break;
case 7:
NSLog(#"Button tag No=%i",buton.tag);
[sec_7 addObject:bton];
break;
case 8:
NSLog(#"Button tag No=%i",buton.tag);
[sec_8 addObject:bton];
break;
default:
NSLog(#"nnnnnnnnnn");
}
}
return [array objectAtIndex:tag];
}

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

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