Silver Challenge Solution... but!


#1

Hi!!

My approach for this challenge is based on the book’s advice that says something like: when a ViewController doesn’t contain subviews, there is no problem to use the loadView method , in other words, create the view programatically, but if a ViewController has subviews, it is a better idea to make use of a XIB to create it visually…

So I created a XIB file for my controller, in my case a MRCHypnosisViewController, added a view object to it, and changed its default class UIView to MRCHypnosisView so it can display the hypno stuff we already have done.

Then I added the UISegmentedControl to that view, and hooked the connections so it ended like this (sc stands for Segmented Control as you probably guessed):

[size=150]My MRCHypnosisViewController.h[/size]

[code]#import <Foundation/Foundation.h>
#import “MRCHypnosisView.h”

@interface MRCHypnosisViewController : UIViewController{
IBOutlet UISegmentedControl *sc;
MRCHypnosisView *hypnoView;
}

@end[/code]

[size=150]My MRCHypnosisViewController.m[/size]

[code]#import “MRCHypnosisViewController.h”

@implementation MRCHypnosisViewController

  • (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {

      //Init the view with the default HypnoView
      hypnoView = [(MRCHypnosisView *)[self view] init];
      
      //Get the tab bar item
      UITabBarItem *tbi = [self tabBarItem];
      
      //Set the label
      [tbi setTitle:@"Hypnosis"];
      
      //Create an image object to hold the bar item image
      //and add it to the tab bar
      UIImage *hypnoImage = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Hypno" ofType:@"png"]];
      [tbi setImage:hypnoImage];
    

    }
    return self;
    }

  • (void)viewDidLoad{
    //Always call the super implementation of viewDidLoad
    [super viewDidLoad];
    NSLog(@“MRCHypnosisViewController loaded its view”);

    //Set the controller as the target for the segmented control behavior
    [sc addTarget:self
    action:@selector(switchCircleColors)
    forControlEvents:UIControlEventValueChanged];
    }

  • (void)switchCircleColors
    {
    if ([sc selectedSegmentIndex] == 0) {
    [hypnoView setCircleColor:[UIColor redColor]];
    }
    else if([sc selectedSegmentIndex] == 1){
    [hypnoView setCircleColor:[UIColor blueColor]];
    }
    else{
    [hypnoView setCircleColor:[UIColor greenColor]];
    }
    }

@end[/code]

The story is that I was a little confused about how to be able to access the accessor I needed (setCircleColor) having changed the class of the view from the XIB (UIView to MRCHypnosisView), I though that I could access it trough [[self view] setCircleColor:] given that change I made, but it couldn’t find it because it was still looking within UIView

So I decided to use something I have seen too much: casting, and all get solved by the next line used with the instance variable I created as you can see in the header above:

Everything works just fine, but I’m not sure if this is the right thing to do, if this is a good or a bad practice/approach to this solution.

I appreciate any comments you have about it.

Have a nice day!