Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

mohaskh

macrumors newbie
Original poster
Oct 27, 2016
2
0
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
 
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.
 
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
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.