PDA

View Full Version : setNeedsDisplay won't call drawRect:




chauhan4
Oct 27, 2009, 09:13 AM
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


//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;
}
- (void)drawRect:(CGRect)rect
{
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;
[self updateInterface];
NSLog(@"Polygon: %@", polygon);
//NSLog(@"The number of sides is %d", polygon.numberOfSides);
}

- (IBAction)increase
{
polygon.numberOfSides = polygon.numberOfSides + 1;
[self updateInterface];
NSLog(@"Polygon: %@", polygon);
//NSLog(@"I'm in the increase method");
//NSLog(@"The number of sides is %d", polygon.numberOfSides);
}

- (void)updateInterface
{
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);
[polyview setNeedsDisplay];
}

- (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...



jeremy.king
Oct 27, 2009, 12:17 PM
Did you remember to connect the polygon view to your outlet instance variable?

chauhan4
Oct 27, 2009, 04:26 PM
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.....

akdude
Dec 1, 2009, 11:56 PM
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)).