Silver Challenge


#1

So I created the segmented control, but I am having trouble with the target/action aspect of it. I have tried a couple of different methods, but I am really stuck. Can someone help me out here, and tell me what I’m doing wrong? I would really appreciate it.

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

@interface HypnosisViewController : UIViewController
{
UISegmentedControl *segmentedControl;
HypnosisView *hypnoView;
}

@property(nonatomic) NSInteger selectedSegmentIndex;

-(void)segmentValueChanged:(id)sender;

@end
[/code]

[code]#import “HypnosisViewController.h”
#import “HypnosisView.h”

@implementation HypnosisViewController

-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
//Call the superclass’s designated initializer
self = [super initWithNibName:nil
bundle:nil];
if (self) {
//Get the tab bar item andset its title
UITabBarItem *tbi = [self tabBarItem];
[tbi setTitle:@“Hypnosis”];

    //Create a UIImage from a file and set it as the image
    UIImage *i = [UIImage imageNamed:@"Hypno.png"];
    [tbi setImage:i];
}

return self;

}

-(void)loadView
{
CGRect frame = [[UIScreen mainScreen]bounds];
HypnosisView *v = [[HypnosisView alloc]initWithFrame:frame];

//Create the segmented control
NSArray *titles = [NSArray arrayWithObjects:@"Blue",@"Red",@"Green", nil];
segmentedControl = [[UISegmentedControl alloc]initWithItems:titles];
[self setView:v];
[v addSubview:segmentedControl];
segmentedControl.frame = CGRectMake(60, 350, 200, 50);

[segmentedControl addTarget:self
                     action:@selector(segmentValueChanged:)
           forControlEvents:UIControlEventValueChanged];

}

-(void)segmentValueChanged:(id)sender
{
int segmentSelected = [segmentedControl selectedSegmentIndex];
if (segmentSelected == 0) {
[hypnoView setCircleColor:[UIColor blueColor]];
} else if (segmentSelected == 1) {
[hypnoView setCircleColor:[UIColor redColor]];
} else if (segmentSelected == 2) {
[hypnoView setCircleColor:[UIColor greenColor]];
}
}

-(void)viewDidLoad
{
[super viewDidLoad];

NSLog(@"HynosisViewController loaded its view");

}
@end
[/code]

[code]#import <Foundation/Foundation.h>

@interface HypnosisView : UIView

@property (nonatomic, strong) UIColor *circleColor;

@end
[/code]

[code]#import “HypnosisView.h”

@implementation HypnosisView

@synthesize circleColor;

-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];

if (self) {
    //All views start with a clear background color
    [self setBackgroundColor:[UIColor clearColor]];
    [self setCircleColor:[UIColor cyanColor]];
}

return self;

}

-(void)drawRect:(CGRect)dirtyrect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect bounds = [self bounds];

//Figure out the center of the bounds rectangle
CGPoint center;
center.x = bounds.origin.x + bounds.size.width / 2.0;
center.y = bounds.origin.y + bounds.size.height / 2.0;

//The radius of the circle should be nearly as big as the view
float maxRadius = hypot(bounds.size.width, bounds.size.height) / 2.0;

//The thickness of the line should be 10 points wide
CGContextSetLineWidth(ctx, 10);

[[self circleColor] setStroke];


for (float currentRadius = maxRadius; currentRadius > 0; currentRadius -= 20) {
    CGContextAddArc(ctx, center.x, center.y, currentRadius, 0.0, M_PI * 2.0, YES);
    CGContextStrokePath(ctx);
}

//Push the string to the top of the stack
CGContextSaveGState(ctx);

//Create a string
NSString *text = @"You are getting sleepy";

//Get a font to draw it in
UIFont *font = [UIFont boldSystemFontOfSize:28];

//Declare the variable textRect of CGRect type
CGRect textRect;

//How big is this string when drawn in this font?
textRect.size = [text sizeWithFont:font];

//Let's put that string in the center of the view
textRect.origin.x = center.x - textRect.size.width / 2.0;
textRect.origin.y = center.y - textRect.size.height / 2.0;

//Set the fill color of the current context to black
[[UIColor blackColor] setFill];

//The shadow will move 4 points to the right and 3 points down from the text
CGSize offset = CGSizeMake(4, 3);

//The shadow will be dark gray
CGColorRef color = [[UIColor darkGrayColor] CGColor];

//Set the shadow of the context with these perameters, all subsequent drawing will be shadowed
CGContextSetShadowWithColor(ctx, offset, 2.0, color);

//Draw the string
[text drawInRect:textRect
        withFont:font];

CGContextRestoreGState(ctx);

CGContextSetLineWidth(ctx, 5);
[[UIColor greenColor] setStroke];

//Set starting point of Horizontal line
CGContextMoveToPoint(ctx, center.x + 50, center.y);
//Set ending point of horizontal line 
CGContextAddLineToPoint(ctx, center.x - 50, center.y);
CGContextStrokePath(ctx);

//Set starting point of Verticle line
CGContextMoveToPoint(ctx, center.x, center.y + 50);
//Set ending point of the verticle line
CGContextAddLineToPoint(ctx, center.x, center.y - 50);
CGContextStrokePath(ctx);

}

-(BOOL)canBecomeFirstResponder
{
return YES;
}

//Lets HypnosisView know and take the shaking action
-(void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (motion == UIEventSubtypeMotionShake) {
NSLog(@“Device started shaking”);
[self setCircleColor:[UIColor orangeColor]];
}
}

-(void)setCircleColor:(UIColor *)clr
{
circleColor = clr;
//Tells HypnosisView it needs to redraw its image to show new UIColor instance
[self setNeedsDisplay];
}

@end[/code]


#2

Can you elaborate on what’s not working?


#3

Yes, when I press a button one of the segmented controls on the simulator, nothing happens. The segment I pressed just stays highlighted and the color of the circle doesn’t change. I know te code is pretty sloppy, but I don’t see why it isn’t working.


#4

I see what the problem is. You never assign the hypnoView ivar in your loadView method. So when you call setCircleColor the received is nil.


#5

Thanks for the help! But I haven’t learned about ivars yet. How would I implement it in loadView?


#6

ivars = instance variables

[code]-(void)loadView
{
CGRect frame = [[UIScreen mainScreen]bounds];
HypnosisView *v = [[HypnosisView alloc]initWithFrame:frame];

//Create the segmented control
NSArray *titles = [NSArray arrayWithObjects:@"Blue",@"Red",@"Green", nil];
segmentedControl = [[UISegmentedControl alloc]initWithItems:titles];
[self setView:v];

hypnoView = v; // you should nil the hypnoView pointer in viewDidUnload

[v addSubview:segmentedControl];
segmentedControl.frame = CGRectMake(60, 350, 200, 50);

[segmentedControl addTarget:self
                     action:@selector(segmentValueChanged:)
           forControlEvents:UIControlEventValueChanged];

}[/code]