7

in Obj-C a switch can only evaluate numbers. I'd like to be able to use it to compare classes of objects, something like this, for instance:

switch (currentSubViewController.class) 
{
     case UITableViewController.class :
          <do stuff>
          break;
     case UICollectionViewController.class :
          <do stuff>
          break;
}

Is there any way to achieve this? I'd really like to be able to use a switch because it makes it so easy to read for different cases, and I can add more cases at any point in the future. Any ideas?

PTTHomps
  • 1,477
  • 2
  • 22
  • 38
  • Assuming you are on iPhone, are you having a separate viewController for each of the subviews ? – Nitin Alabur May 19 '13 at 23:28
  • yes, one view controller for each one. Really, I want to see which view controller is currently being presented. I could easily keep track of it by just using a number value (as a global, or whatever), such as int currentlyPresentedController = whatever, and then just set it's value manually whenever I switch controllers, but I don't trust that solution very much, as forgetting to set the value could screw things up. Also, the value could somehow get out of sync with the actual controller being presented. More reliable, I think, to test the class directly. – PTTHomps May 20 '13 at 12:53
  • To clarify, the original motivation behind this was to be able to cycle through a set of view controllers being presented when a 'cycle' button is pressed by the user. If controller of class A is currently being presented, then switch to B. If B is being presented, then switch to C, etc. – PTTHomps May 20 '13 at 12:58
  • aaaaaand I just spent 20 minutes fixing a bug caused by using the int currentlyPresentedController technique I mentioned. :P I am right to distrust it. – PTTHomps May 20 '13 at 14:24
  • just want to be sure you have read this http://stackoverflow.com/questions/1141015/is-it-wise-to-nest-uiviewcontrollers-inside-other-uiviewcontrollers-like-you-w before you carry on with your implementation. I'm still not sure what advantage your expected implementation gives you. – Nitin Alabur May 20 '13 at 15:23

5 Answers5

9

As described in this forum post you would be better off applying the Liskov Substitution Principle and put the <do stuff> logic in the actual class, and then call a method shared by a superclass all these classes inherit (or a protocol in Obj-C if you're planning to have this logic shared across totally different classes).

This encapsulates all the logic in each implementation/sub-class without a higher level class needing to worry about every single possible implementation you might have. This improves maintainability and is more common in Object Oriented Programming as opposed to plain old procedural programming.

Aram Kocharyan
  • 20,165
  • 11
  • 81
  • 96
  • +1 Great answer. I have a feeling that the OP's original mentality was for a view controller to respond a certain way depending on the object's class. Is there a time when that approach is permissible, or would you always abide by the Substitution Principle? – The Kraken May 19 '13 at 23:35
  • 1
    Thanks, `respond a certain way` I think implies that you'd want the class to decide what to do and not an omnipotent controller. I'd probably only use a switch for what it's intended here - switching between primitive values. I don't recall relying on it heavily though :) – Aram Kocharyan May 19 '13 at 23:39
  • The intent is actually to be able to cycle between the view controller types. If it's type A, then present type B. If it's type B, then present type C, etc. So to my mind such a thing really belongs in the master controller class rather than the subclass. – PTTHomps May 20 '13 at 12:57
  • 1
    This IS useful info though. :) – PTTHomps May 20 '13 at 12:57
  • @TraxusIV Ah ok, you could use the modulo function: `viewIndex = (viewIndex + 1) % views.count`. And then set the current view as the object in the `views` `NSArray` object with that index. That is if cycling is all you need without extra logic. – Aram Kocharyan May 20 '13 at 15:49
1

The switch statement only works with integer types. You need a big if-else block.

If you really want to force a switch statement then you could work out something using a fixed array of classes and base the switch off of the index position of the class you are checking. But for readability in the case statements, you would need to define a set of constants representing the index position of each class. That's a lot of work and code to maintain just to avoid and if-else block.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
0

Thats not possible. You have to use if-elseif statement like this

if ([currentSubViewController isMembefOrClass:[UITableViewController class]]) 
{
    <do stuff>
} else if ([currentSubViewController isMemberOfClass:[UICollectionViewController class]]) {

}

notice that I use isMemberOfClass: to simulate what switch-case statement will do. But in most of the cases you want to use isKindOfClass:

Bryan Chen
  • 45,816
  • 18
  • 112
  • 143
0

You can use a dictionary literal.

((void(^)())@{
NSStringFromClass([UITableViewController class]) : [^{
    // stuff
} copy],
NSStringFromClass([UICollectionViewController class]) : [^{
    // stuff
} copy]
}[NSStringFromClass([currentSubViewController class])])();

NOTE: This is just for fun. Please don't take it as a serious suggestion.

Seriously use @AramKocharyan answer.

Jeffery Thomas
  • 42,202
  • 8
  • 92
  • 117
0

One way is to build a data structure mapping the classes you care about to values in an enum. This will be a lot of boiler plate code.

Unfortunately, Objective-C has no object oriented switch conditional like languages such as Ruby. It only has the C switch statement. A case in the C switch statement requires an integer constant and this is what prevents more dynamic approaches using C switch statements. The C enum type also works with constants. This means neither one can be generated at runtime, but could be at compile time.

C enums and switch statements work well together but not so hot for objects.

So, you might be better off doing compound if-else statements to do your comparisons here.

uchuugaka
  • 12,679
  • 6
  • 37
  • 55