1. Welcome to the new MacRumors forums. See our announcement and read our FAQ

setNeedsDisplay won't call drawRect:

Discussion in 'iPhone/iPad Programming' started by chauhan4, Oct 27, 2009.

  1. macrumors newbie

    I am trying to complete assignment 3 from the Stanford lectures on iTunes U. They're real interesting but I've run into a problem. I'm trying to update a subview in a window to display the shape of a polygon but setNeedsDisplay is called once and never again. Could someone please help me resolve this bug. Thanks

    //PolygonView header file
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    #import "PolygonShape.h"
    @interface PolygonView : UIView/* Specify a superclass (eg: NSObject or NSView) */ {
        IBOutlet PolygonShape *polyShape;
    @property (retain) PolygonShape *polyShape;
    + (NSArray *)pointsForPolygonInRect:(CGRect)rect numberOfSides:(int)numberOfSides;
    //PolygonView implementation file
    #import "PolygonView.h"
    @implementation PolygonView
    @synthesize polyShape;
    + (NSArray *)pointsForPolygonInRect:(CGRect)rect numberOfSides:(int)numberOfSides
    	CGPoint center = CGPointMake(rect.size.width / 2.0, rect.size.height / 2.0);
    	float radius = 0.9 * center.x;
    	NSMutableArray *result = [NSMutableArray array];
    	float angle = (2.0 * M_PI) / numberOfSides;
    	float exteriorAngle = M_PI - angle;
    	float rotationDelta = angle - (0.5 * exteriorAngle);
    	for (int currentAngle = 0; currentAngle < numberOfSides; currentAngle++)
    		float newAngle = (angle * currentAngle) - rotationDelta;
    		float curX = cos(newAngle) * radius;
    		float curY = sin(newAngle) * radius;
    		[result addObject:[NSValue valueWithCGPoint:CGPointMake(center.x + curX, center.y + curY)]];
    	return result;
    [B]- (void)drawRect:(CGRect)rect[/B]
    	NSLog(@"Entering drawRect function");
    	CGRect bounds = [self bounds];//Here bounds is reference to the subview that was created
    	[[UIColor blueColor] set];
    	UIRectFill(bounds);//fills the color of the bounds
    	NSArray *arraypoints = [PolygonView pointsForPolygonInRect:bounds numberOfSides:polyShape.numberOfSides];//we don't use self here as this is a class method that begins with a '+' (I think)
    	//The above statement returns an array with and x and y coordinates of the polygon that is generated using information of numberOfSides	
    	CGContextRef context = UIGraphicsGetCurrentContext();//gets the current graphic context which is what we use when you're overriding the drawRect funtion
    	CGContextBeginPath(context);//begin drawing the polygon
    	CGPoint currentPoint = [[arraypoints objectAtIndex:0] CGPointValue];//retrieve the first coordinate point of the polygon from the array
    	CGContextMoveToPoint(context, currentPoint.x, currentPoint.y);//move to the first point of the array
    	//Found this code in the documentation to enumerate through an array using NSEnumerator
    	NSEnumerator *enumerator = [arraypoints objectEnumerator];
    	id object;
    	while((object = [enumerator nextObject]))
    		currentPoint = [object CGPointValue];
    		CGContextAddLineToPoint(context, currentPoint.x, currentPoint.y);
    	[[UIColor redColor] setFill];
    	[[UIColor blackColor] setStroke];
    	CGContextDrawPath(context, kCGPathFillStroke);
    	NSLog(@"drawRect is being called");
    //Controller header file
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    #import "PolygonShape.h"
    #import "PolygonView.h"
    @interface Controller : NSObject/* Specify a superclass (eg: NSObject or NSView) */ {
        IBOutlet UIButton *decreaseButton;
        IBOutlet UIButton *increaseButton;
        IBOutlet UILabel *numberOfSidesLabel;
        IBOutlet PolygonShape *polygon;
        IBOutlet PolygonView *polyview;
    - (IBAction)decrease;
    - (IBAction)increase;
    - (void)awakeFromNib;
    - (void)updateInterface;
    //Controller implementation file
    #import "Controller.h"
    #import "PolygonShape.h"
    #import "PolygonView.h"
    @implementation Controller
    - (IBAction)decrease 
        //NSLog(@"I'm in the decrease method");
    	polygon.numberOfSides = polygon.numberOfSides - 1;
    	[B][self updateInterface];[/B]
    	NSLog(@"Polygon: %@", polygon);
    	//NSLog(@"The number of sides is %d", polygon.numberOfSides);
    - (IBAction)increase 
    	polygon.numberOfSides = polygon.numberOfSides + 1;
    	[B][self updateInterface];[/B]
    	NSLog(@"Polygon: %@", polygon);
    	//NSLog(@"I'm in the increase method");
    	//NSLog(@"The number of sides is %d", polygon.numberOfSides);
    [B]- (void)updateInterface[/B]
    	if(polygon.numberOfSides > polygon.minimumNumberOfSides)
    		decreaseButton.enabled = YES;
    		decreaseButton.enabled = NO;
    	if(polygon.numberOfSides < polygon.maximumNumberOfSides)
    		increaseButton.enabled = YES;
    		increaseButton.enabled = NO;
    	numberOfSidesLabel.text = [NSString stringWithFormat:@"%d", polygon.numberOfSides];
    	NSLog(@"The number of sides is %d", polygon.numberOfSides);
    	[B][polyview setNeedsDisplay];[/B]
    - (void)awakeFromNib
    	//PolygonShape *poly = [PolygonShape alloc]; 
    	//[polygon initWithNumberOfSides:numberOfSidesLabel.text.integerValue minimumNumberOfSides:3 maximumNumberOfSides:12];
    	[self updateInterface];
    	NSLog(@"My polygon = %@", polygon);
    	//numberOfSidesLabel.text = [NSString stringWithFormat:@"%@", polygon.numberOfSides];
    	//[polygon release];
    Thanks for your help in advance...
  2. macrumors 603


    Did you remember to connect the polygon view to your outlet instance variable?
  3. macrumors newbie

    Oh, i'm sorry I forgot to update this....I fixed the problem, one of my connections had broken in IB for some reason and thats why it wouldn't display.....Thanks anyway.....
  4. macrumors newbie

    I'm working my way though this class as well, but I'm running into a semi-issue. I was having the same issue as the OP where setNeedsDisplay wasn't doing anything. I then linked the PolyView to the controller (or the other way around, still kinda confused about that). This made the call take place, but the polygon was never updating. If I add the line of code

    [polygonView setPolygon:polygon];
    then the polygon in the view updates and everything draws correctly. I might be wrong, but shouldn't this line of code never be needed? I have

    PolygonView with a polygon instance variable linked to the polygon object in the mainview.xib

    Controller with a polygon and polygonView instance variables linked to the polygon object and the view respectively.

    and finally

    Polygon linked to both the controller and polygonview.

    I figure with all these links there should only be the ONE polygon ever in existence, and that pointers are passed around correctly, but like I said, if I don't call that line of code above, the updating draw method is called, but nothing changes (did a
    NSLog(@"%@", polygon)
    and it was the same polygon I started with (5 sides, 3 min, 12 max)).

Share This Page