Problem to redraw a view

Discussion in 'iOS Programming' started by mohaskh, Oct 27, 2016.

  1. mohaskh macrumors newbie

    Joined:
    Oct 27, 2016
    #1
    Hello everybody,

    I'm new in this forum and i'm french (sorry if my english is not very well)
    Here is my first post, i'm beginner on programming in objective C and i have some problems.

    I'm programming a mini application that display random points in a custom view.
    The user enter a number of point in a UITexfield and then he clicks on a button that execute a function which display random points in the view.
    But the points don't appear in the view despite i use the function setNeedDisplay :

    ViewController.h

    Code:
    #import <UIKit/UIKit.h>
    #import "maVue.h"
    
    @interface ViewController : UIViewController{
        IBOutlet UITextField *ptsNumber;
        IBOutlet UILabel *piResult;
        
        IBOutlet maVue *contentView;
        int contentViewWidth;
        int contentViewHeight;
        
    }
    
    - (IBAction)calculPI:(id)sender;
    
    @end
    ViewController.m
    Code:
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (id) initWithCoder:(NSCoder *)aDecoder {
        NSLog(@"initWithCoder");
        self = [super initWithCoder:aDecoder];
        if (self) {
    
        }
        return self;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    - (float)generateRandomNumberBetweenMin:(int)min Max:(int)max{
        return (float) ((arc4random() % (max-min+1)) + min);
    }
    
    - (IBAction)calculPI:(id)sender {
        CGRect viewBounds = [contentView bounds];
        contentViewWidth = (int) viewBounds.size.width;
        contentViewHeight = (int) viewBounds.size.height;
        
        float ptsNumber = [ptsNumber.text floatValue];
        float ptsInTheCircle = 0;
        float randX = 0;
        float randY = 0;
        CGPoint point;
        
        for(int i=0; i<ptsNumber; i++){
            randX = [self generateRandomNumberBetweenMin:0 Max:contentViewWidth];
            randY = [self generateRandomNumberBetweenMin:0 Max:contentViewHeight];
        
            point.x = randX;
            point.y = randY;
            
            NSValue *ptsValueStore = [NSValue valueWithCGPoint:point];
    
            [contentView addPoint:ptsValueStore];
            
            printf("view bounds %d + %d\n", contentViewWidth, contentViewHeight);
            printf("%f + %f\n", point.x, point.y);
        }
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        [self.view endEditing:YES];
    }
    
    @end
    maVue.h
    Code:
    #import <UIKit/UIKit.h>
    
    @interface maVue : UIView
        @property (nonatomic, strong) NSMutableArray *pts;
        -(void) addPoint:(NSValue *)point;
    @end

    maVue.m

    Code:
    #import "maVue.h"
    
    @implementation maVue
        @synthesize pts;
    
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    - (void)drawRect:(CGRect)rect {
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGRect bounds = [self bounds];
        
        //Initialisation du centre du repère
        CGPoint center;
        center.x = bounds.origin.x;
        center.y = bounds.origin.y;
    
        //Initialisation du rayon + traçé de l'arc
        float maxRadius = bounds.size.width;
        CGContextSetLineWidth(ctx, 1);
        CGContextSetRGBStrokeColor(ctx, 1.0, 0, 0, 1.0);
        CGContextAddArc(ctx, center.x, center.y, maxRadius, 0.0, 2 * M_PI, YES);
        CGContextStrokePath(ctx);
        
        printf("my view bounds : %f\n", maxRadius);
        printf("nbpoint : %d\n",(int) [self.pts count]);
        
        CGPoint pt;
        for(NSValue *valuePt in self.pts){
            pt = [valuePt CGPointValue];
            
            //Ajout des points sur le cercle
            CGRect borderRect = CGRectMake(pt.x, pt.y, 1.0, 1.0);
            CGContextRef context = UIGraphicsGetCurrentContext();
            CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
            CGContextFillEllipseInRect (context, borderRect);
            CGContextFillPath(context);
        }
    }
    
    -(void) addPoint:(NSValue *)point {
        [self.pts addObject:point];
         printf("Add nbpoint : %D\n",(int) [self.pts count]);
        [self setNeedsDisplay];
    }
    
    @end
    Anybody have a solution ?

    Thanks
     
  2. PhoneyDeveloper macrumors 68040

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #2
    I don't know the answer just from reading the code. Here are a few comments:

    Your code is written in a kind of antique style. I guess the book or tutorial you're using is a few years old. However, it should still work.

    Is your DrawRect method called? Do you see the printf() output?

    Are your points inside the rect passed to DrawRect?

    What happens if you fillRect: the rect passed into DrawRect?

    You don't need to fetch the context for each point. The context won't change for each point.
     
  3. mohaskh thread starter macrumors newbie

    Joined:
    Oct 27, 2016
    #3
    Hello,

    Thanks for your help.
    But i tried another method that work fine.

    I create a custom "Point" object like that :

    Point.h
    Code:
    #import <Foundation/Foundation.h>
    
    @interface myPoint : NSObject
    
        @property (nonatomic, assign) float x;
        @property (nonatomic, assign) float y;
        @property (nonatomic, assign) float red;
        @property (nonatomic, assign) float green;
        @property (nonatomic, assign) float blue;
    
    -(id)init :(float)x :(float)y :(float)red :(float)green :(float)blue;
    
    @end
    Point.m
    Code:
    #import "myPoint.h"
    
    @implementation myPoint
        @synthesize x;
        @synthesize y;
        @synthesize red;
        @synthesize green;
        @synthesize blue;
    
    -(id) init :(float)i :(float)j :(float)r :(float)g :(float)b  {
        x = i;
        y = j;
        red = r;
        green = g;
        blue = b;
        return self;
    }
    
    -(float) getX{
        return x;
    }
    
    -(float) getY{
        return y;
    }
    
    -(float) getRed{
        return red;
    }
    
    -(float) getGreen{
        return green;
    }
    
    -(float) getBlue{
        return blue;
    }
    
    -(void) setX:(float)i{
        x = i;
    }
    
    -(void) setY:(float)j{
        y = j;
    }
    
    -(void) setRed:(float)r{
        red = r;
    }
    
    -(void) setGreen:(float)g{
        green = g;
    }
    
    -(void) setBlue:(float)b{
        blue = b;
    }
    @end
    
    ViewController.h
    Code:
    #import <UIKit/UIKit.h>
    #import "maVue.h"
    
    @interface ViewController : UIViewController{
        IBOutlet UITextField *pointNumber;
        IBOutlet UILabel *piValue;
        IBOutlet maVue *contentView;
    }
    
    -(IBAction)calcul:(id)sender;
    
    @end
    
    ViewController.m
    Code:
    #import "ViewController.h"
    #import "myPoint.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (id) initWithCoder:(NSCoder *)aDecoder {
        NSLog(@"initWithCoder");
        self = [super initWithCoder:aDecoder];
        if (self) {
            
        }
        return self;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    - (IBAction)calcul:(id)sender {
        printf("\nCalcul\n");
        
        NSMutableArray *points = [[NSMutableArray alloc] init];
        
        float totalPts = [pointNumber.text floatValue];
        float ptsInTheCircle = 0;
        float pi = 0;
        float randX = 0;
        float randY = 0;
        
        CGRect viewBound = [contentView bounds];
        float maxRadius = [contentView maxRadius];
    
        for(int i=0; i<(int)totalPts; i++){
            randX = [self generateRandomNumberBetweenMin:viewBound.origin.x Max:viewBound.size.width];
            randY = [self generateRandomNumberBetweenMin:viewBound.origin.y Max:viewBound.size.height];
            
            myPoint *pt = [myPoint alloc];
            if([self inTheCircle:randX :randY :maxRadius]){
                pt = [pt init:randX :randY :0.0 :0.0 :1.0];
                [points addObject:pt];
                ptsInTheCircle++;
            }else{
                pt = [pt init:randX :randY :0.0 :1.0 :0.0];
                [points addObject:pt];
            }
        }
        
        pi = [self calculPI:totalPts :ptsInTheCircle];
        printf("Pi = %f\n\n", pi);
        
        NSString *piEqualString = @"π ≈ ";
        NSString *piStringValue=[piEqualString stringByAppendingFormat:@"%f",pi];
        piValue.text = piStringValue;
        
        [contentView setPoints:points];
    }
    
    - (float)generateRandomNumberBetweenMin:(int)min Max:(int)max{
        return (float) ((arc4random() % (max-min+1)) + min);
    }
    
    - (Boolean)inTheCircle:(float)x :(float)y :(float)radian{
        return ((x*x) + (y*y) <= (radian*radian));
    }
    
    -(float)calculPI:(float)ptsTotal :(float)ptsInTheCircle{
        return (4.0*ptsInTheCircle)/ptsTotal;
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        [self.view endEditing:YES];
    }
    
    @end
    
    maVue.h
    Code:
    #import <UIKit/UIKit.h>
    
    @interface maVue : UIView
        @property (nonatomic, strong) NSMutableArray *points;
        @property (nonatomic, assign) float maxRadius;
    @end
    maVue.m
    Code:
    #import "maVue.h"
    #import "myPoint.h"
    
    @implementation maVue
    
    @synthesize points;
    @synthesize maxRadius;
    
    - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame];
        if (self) {
            points = [points init];
        }
        return self;
    }
    
    - (void)drawRect:(CGRect)rect {   
        //printf("Init : %f\n", self.nbPoints);
      
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGRect bounds = [self bounds];
        
        //Initialisation de l'origine du repère
        CGPoint center;
        center.x = bounds.origin.x;
        center.y = bounds.origin.y;
        
        //Initialisation du rayon + traçé de l'arc
        maxRadius = bounds.size.width;
        
        float x = 0;
        float y = 0;
        float red = 0;
        float green = 0;
        float blue = 0;
        
        for(int i=0; i<(int)[points count]; i++){
            myPoint *pt = [points objectAtIndex:i];
            x = pt.x;
            y = pt.y;
            red = pt.red;
            green = pt.green;
            blue = pt.blue;
            
            CGRect borderRect = CGRectMake(x, y, 1.0, 1.0);
            CGContextRef context = UIGraphicsGetCurrentContext();
            CGContextSetRGBFillColor(context, red, green, blue, 1.0);
            CGContextFillEllipseInRect (context, borderRect);
            CGContextFillPath(context);
        }
        
        CGContextSetLineWidth(ctx, 1);
        CGContextSetRGBStrokeColor(ctx, 1.0, 0, 0, 1.0);
        CGContextAddArc(ctx, center.x, center.y, maxRadius, 0.0, 2 * M_PI, YES);
        CGContextStrokePath(ctx);
    }
    
    - (void) setPoints:(NSMutableArray *)pts{
        points = pts;
        [self setNeedsDisplay];
    }
    
    @end
    
    I think the problem was that i executed a loop "for" in "drawRect" method. So i calculate pi value before draw points in the view.

    Thanks
     

Share This Page