Silver Challenge: "view outlet not set" exception


#1

I am working on the Silver Challenge, and every OTHER time I run my project I get the following error (the project always compiles without errors). The remaining times I run the project, it runs fine.

Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘-[UIViewController _loadViewFromNibNamed:bundle:] loaded the “HypnosisViewController” nib but the view outlet was not set.’

I added a UISegmentedControl to the HypnosisView using IB in the following manner:

  1. Added a UIView to the .xib file
  2. Changed the Class of that UIView to “HypnosisView”
  3. Changed the Class of File’s Owner to “HypnosisViewController”
  4. Added a UISegmentedControl as a subview of the HypnosisView
  5. Connected UISegmentedControl to my changeCircleColor method
  6. Connected my HypnosisView instance variable (hv) in File’s Owner to the HypnosisView object in the .xib file
  7. Connected view in File’s Owner to the HypnosisView object in the .xib file

HypnosisView.h

#import <Foundation/Foundation.h>

@interface HypnosisView : UIView

@property (nonatomic, strong) UIColor *circleColor;

@end

HypnosisView.m

#import "HypnosisView.h"

@implementation HypnosisView

@synthesize circleColor;

- (void)drawRect:(CGRect)rect
{
    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);
    
    // The color of the line should be gray (red/green/blue = 0.6, alpha = 1.0)
    //CGContextSetRGBStrokeColor(ctx, 0.6, 0.6, 0.6, 1.0);
    //[[UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:1] setStroke];
    [[self circleColor] setStroke];
    
    // Draw concentric circles from the outside in
    for (float currentRadius = maxRadius; currentRadius > 0; currentRadius -= 20) {
        // Add a path to the context
        CGContextAddArc(ctx, center.x, center.y, currentRadius, 0.0, M_PI*2.0, YES);
        
        // Perform drawing instruction; removes path
        CGContextStrokePath(ctx);
    }
    
    // Create a string
    NSString *text = @"You are getting sleepy.";
    
    // Get a font to draw it in
    UIFont *font = [UIFont boldSystemFontOfSize:28];
    
    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 in color
    CGColorRef color = [[UIColor darkGrayColor] CGColor];
    
    // Set the shadow of the context with these parameters,
    // all subsequent drawing will be shadowed
    CGContextSetShadowWithColor(ctx, offset, 2.0, color);
    
    // Draw the string
    [text drawInRect:textRect
            withFont:font];
}

//- (id)initWithFrame:(CGRect)frame
//{
//    self = [super initWithFrame:frame];
//    if (self) {
//        // All HypnosisViews start with a clear background color
//        [self setBackgroundColor:[UIColor clearColor]];
//        [self setCircleColor:[UIColor lightGrayColor]];
//    }
//    return self;
//}

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

- (void)motionBegan:(UIEventSubtype)motion 
          withEvent:(UIEvent *)event
{
    if (motion == UIEventSubtypeMotionShake) {
        NSLog(@"Device started shaking!");
        [self setCircleColor:[UIColor redColor]];
    }
}

- (void)setCircleColor:(UIColor *)clr
{
    circleColor = clr;
    [self setNeedsDisplay];
}

@end

HypnosisViewController.h

#import <Foundation/Foundation.h>
#import "HypnosisView.h"

@interface HypnosisViewController : UIViewController
{
    __weak IBOutlet HypnosisView *hv;
}

- (IBAction)changeCircleColor:(UISegmentedControl *)sender;

@end

HypnosisViewController.m

#import "HypnosisViewController.h"
#import "HypnosisView.h"

@implementation HypnosisViewController

//- (void)loadView
//{
//    // Create a view
//    CGRect frame = [[UIScreen mainScreen] bounds];
//    HypnosisView *v = [[HypnosisView alloc] initWithFrame:frame];
//    
//    // Set it as *the* view of this view controller
//    [self setView:v];
//}

- (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
        UITabBarItem *tbi = [self tabBarItem];
        
        // Give it a label
        [tbi setTitle:@"Hypnosis"];
        
        // Create a UIImage from a file
        // This will use Hypno@2x.png on retina display devices
        UIImage *i = [UIImage imageNamed:@"Hypno.png"];
                      
        // Put that image on the tab bar item
        [tbi setImage:i];
                      
    }
    return self;
}

- (void)viewDidLoad
{
    // Always call the super implementation of viewDidLoad
    [super viewDidLoad];
    [hv setBackgroundColor:[UIColor clearColor]];
    [hv setCircleColor:[UIColor lightGrayColor]];
    
    NSLog(@"HypnosisViewController loaded its view.");
}

- (void)changeCircleColor:(UISegmentedControl *)sender
{
    if ([sender selectedSegmentIndex] == 0) {
        [hv setCircleColor:[UIColor redColor]];
    } else if ([sender selectedSegmentIndex] == 1) {
        [hv setCircleColor:[UIColor greenColor]];
    } else if ([sender selectedSegmentIndex] == 2) {
        [hv setCircleColor:[UIColor blueColor]];
    }
}

@end

#2

If I were you I would start a new project from scratch (do not copy the old one), follow the same procedure to setup the UI connections, see if the same thing happens again.


#3

Problem solved! I accidentally created two HypnosisViewController.xib files in my project. I deleted the one I wasn’t using, and the problem went away.