setNeedsDisplay won't call drawRect:

Discussion in 'iOS Programming' started by chauhan4, Oct 27, 2009.

  1. macrumors newbie

    Joined:
    Oct 23, 2009
    #1
    hi,
    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

    Code:
    //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;
    
    @end
    
    //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);
    	}
    	CGContextClosePath(context);
    	[[UIColor redColor] setFill];
    	[[UIColor blackColor] setStroke];
    	CGContextDrawPath(context, kCGPathFillStroke);
    	NSLog(@"drawRect is being called");
    	return;
    }
    	
    @end
    
    //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;
    
    @end
    
    //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]
    {
    	NSLog(@"Updating");
    	if(polygon.numberOfSides > polygon.minimumNumberOfSides)
    	{
    		decreaseButton.enabled = YES;
    	}
    	else
    	{
    		decreaseButton.enabled = NO;
    	}
    	
    	if(polygon.numberOfSides < polygon.maximumNumberOfSides)
    		increaseButton.enabled = YES;
    	else
    		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];
    }
    @end
    
    
    Thanks for your help in advance...
     
  2. macrumors 603

    jeremy.king

    Joined:
    Jul 23, 2002
    Location:
    Fuquay Varina, NC
    #2
    Did you remember to connect the polygon view to your outlet instance variable?
     
  3. thread starter macrumors newbie

    Joined:
    Oct 23, 2009
    #3
    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

    Joined:
    Mar 5, 2009
    #4
    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

    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
    Code:
    NSLog(@"%@", polygon)
    and it was the same polygon I started with (5 sides, 3 min, 12 max)).
     

Share This Page