Regarding Silver Challenge


#1

I’m currently working on adding the UISegmentedControl programmatically. I was able to set up a target action for my UISegmentedControl that updates the circleColor property of BNRHypnosisView using its setter (I made the setter public in the BNRHypnosisView.h). I noticed that the setter calls [self setNeedsDisplay] to redraw the circles with the correct color. I’m not sure why the circle’s colors doesn’t change when I change the value in the segmentedControl.

I instantiated the UISegmentedControl in loadView method of BNRHypnosisViewController. Also I added a private property named hypnosisView in the BNRHypnosisViewController to keep track of the BNRHypnosisView. Here’s the code that I added:

  • (void)loadView
    {
    // Create a view

    // Create UISegmented Control
    UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@“red”,@“green”,@“blue”]];
    segmentedControl.frame = CGRectMake(30,200,250,50);
    segmentedControl.selectedSegmentIndex = 0;
    segmentedControl.tintColor = [UIColor blackColor];
    [segmentedControl addTarget:self
    action:@selector(valueChanged:)
    forControlEvents:UIControlEventValueChanged];
    // Set it as the view of this view controller
    self.view = [self hypnosisView];
    }

  • (void)valueChanged:(UISegmentedControl *)segment
    {
    BNRHypnosisView *hv = [self hypnosisView];
    if (segment.selectedSegmentIndex == 0){
    // circles are red
    NSLog(@“red!”);
    [hv setCircleColor:[UIColor colorWithRed:1.0
    green:0
    blue:0
    alpha:1.0]];
    } else if (segment.selectedSegmentIndex == 1){
    NSLog(@“green!”);
    [hv setCircleColor:[UIColor colorWithRed:0
    green:1.0
    blue:0
    alpha:1.0]];
    } else if (segment.selectedSegmentIndex == 2){
    NSLog(@“blue!”);
    [hv setCircleColor:[UIColor colorWithRed:0.0
    green:0.0
    blue:1.0
    alpha:1.0]];
    }
    }

How do I get the screen to display the proper color? The NSLog outputs properly in the console when I change selectedSegments


#2

I got my segmented control to work, but I’m not sure I like it. :slight_smile:

  1. In BNRHypnosisView.h I moved the circleColor Property to the .h file. This allowed me to access the color from another file
  2. In BNRHypnosisViewController.m the BNRHypnosisView was being created and alloc/init in the loadView method. I changed this to an instance variable

@implementation BNRHypnosisViewController { BNRHypnosisView *backgroundView; }

then alloc/init it in loadView

// Create a View backgroundView = [[BNRHypnosisView alloc] init];

The following is my code to setup the segmented control in BNRHypnosisViewController.m

UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@“Red”, @“Green”, @“Blue”]];

segmentedControl.frame = CGRectMake(20,480,280,30); segmentedControl.backgroundColor = [UIColor whiteColor]; [segmentedControl addTarget:self action:@selector(colorSegmentedControl:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:segmentedControl];

and this is the code to set the color which is also in BNRHypnosisViewController.m Now that backgroundView is available to the entire file, I can easily set the colors;

-(void)colorSegmentedControl:(UISegmentedControl *)segment { if (segment.selectedSegmentIndex == 0) { [backgroundView setCircleColor:[UIColor redColor]]; } else if (segment.selectedSegmentIndex == 1) { [backgroundView setCircleColor:[UIColor greenColor]]; } else if (segment.selectedSegmentIndex == 2) { [backgroundView setCircleColor:[UIColor blueColor]]; } }


#3

I tried another way of accessing the circleColor from within the BNRHypnosisViewController: Adding the segmentedControl as a sub-view to backgroundView I then still have access to it via superview.
First, as the others mention, get circleColor from class extension to a property in BNRHypnoisView.h:

@property (nonatomic) UIColor *circleColor;

The code fragment in BNRHypnosisViewController.m then looks like this:

[code]- (void)loadView
{
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@“Red”, @“Green”, @“Blue”]];
segmentedControl.selectedSegmentIndex = 0;
segmentedControl.frame = CGRectMake(20, 380, 280, 30);
segmentedControl.backgroundColor = [UIColor whiteColor];
[segmentedControl addTarget:self action:@selector(segmentAction:) forControlEvents:UIControlEventValueChanged];

// create a view
BNRHypnosisView *backgroundView = [[BNRHypnosisView alloc] init];
// add segmentControl as subview !!!
[backgroundView addSubview:segmentedControl];
// set it as *the* view of this view controller
self.view = backgroundView;

}
[/code]

and here is the action, which gets called from segmentedControl:

- (IBAction)segmentAction:(id)sender { UISegmentedControl *segmentControl = (UISegmentedControl *)sender; NSLog(@"Segment clicked %d", segmentControl.selectedSegmentIndex); BNRHypnosisView *hv = (BNRHypnosisView *)segmentControl.superview; if (segmentControl.selectedSegmentIndex==0) hv.circleColor = [UIColor redColor]; if (segmentControl.selectedSegmentIndex==1) hv.circleColor = [UIColor greenColor]; if (segmentControl.selectedSegmentIndex==2) hv.circleColor = [UIColor blueColor]; }


#4

Hi all good responses!
I know it is good practice to use ViewControllers to manage subviews, but would it not be possible to just add the UISegmentedControl in the initialiser of BNRHypnosisView and set the color locally?


#5

Yes, it is possible. But you already mentioned: controllers should stay with controllers. That’s also what the challenge suggests (as far as I understand it): put the segmentControl in BNRHypnosisViewController.
I think exposing color as property isn’t a big deal. Actually IMHO it’s where it should belong to. That way you have a nicely configurable HypnosisView that you can reuse in other circumstances.