7

Here's what I want to do:

I have a UIBezierPath and I want to pass it to some method for it to be drawn. Or simply draw it from the method in which it is created.

I'm not sure how to indicate which view it should be drawn in. Do all methods for drawing have to start with

- (void)drawRect:(CGRect)rect { ...} ?

can I do

- (void)drawRect:(CGRect)rect withBezierPath:(UIBezierPath*) bezierPath { ... } ??

How do I call this function, or method, from another method?

Sebastian
  • 7,670
  • 5
  • 38
  • 50
Lordof Theflies
  • 301
  • 1
  • 6
  • 16
  • See [How to draw a Bézier path in a custom view](http://stackoverflow.com/a/34659468/3681880) for a full explanation with an example. – Suragch Jan 07 '16 at 15:56

5 Answers5

21

drawRect: is something that is invoked automatically when you message setNeedsDisplay or setNeedsDisplayInRect: on a view. You never call drawRect: directly.

However you are right in saying that all drawing operations are done within the drawRect: method. Typical implementation would be,

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();

    /* Do your drawing on `context` */
}

Since you are using UIBezierPaths, you will need to maintain an array of bezier paths that you will need to draw and then call setNeedsDisplay when something changes.

- (void)drawRect:(CGRect)rect {    
    for ( UIBezierPath * path in bezierPaths ) {
        /* set stroke color and fill color for the path */
        [path fill];
        [path stroke];
    }
}

where bezierPaths is an array of UIBezierPaths.

Fran Sevillano
  • 8,103
  • 4
  • 31
  • 45
Deepak Danduprolu
  • 44,595
  • 12
  • 101
  • 105
7

First, save your path in an ivar

@interface SomeView {
  UIBezierPath * bezierPath;
}
@property(nonatomic,retain) UIBezierPath * bezierPath;
...
@end
....
- (void)someMethod {
     self.bezierPath = yourBezierPath;
     [self setNeedsDisplayInRect:rectToRedraw];
}

in -drawRect:

- (void)drawRect:(CGRect)rect {
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(currentContext, 3.0);
    CGContextSetLineCap(currentContext, kCGLineCapRound);
    CGContextSetLineJoin(currentContext, kCGLineJoinRound);
    CGContextBeginPath(currentContext);
    CGContextAddPath(currentContext, bezierPath.CGPath);
    CGContextDrawPath(currentContext, kCGPathStroke);
}
ZhangChn
  • 3,154
  • 21
  • 41
4

When you need to custom your view, you can overwrite -drawRect: on the subclass:

- (void)drawRect:(CGRect)rect
{
  // config your context
  [bezierPath stroke];
}

Edit: directly using -stroke make code more compact.

drewish
  • 9,042
  • 9
  • 38
  • 51
cxa
  • 4,238
  • 26
  • 40
2

you can do something like following. just define a UIColor *setStroke; in .h file and you need to set this strokeColor object before your you call [myPath strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];

 - (void)drawRect:(CGRect)rect
    {
        [strokeColor setStroke]; // this method will choose the color from the receiver color object (in this case this object is :strokeColor)
        for(UIBezierPath *_path in pathArray)
            [myPath strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
    }

    #pragma mark - Touch Methods
    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        myPath=[[UIBezierPath alloc]init];
        myPath.lineWidth = currentSliderValue;

        UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
        [myPath moveToPoint:[mytouch locationInView:self]];
        [pathArray addObject:myPath];
    }
    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    {
        UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
        [myPath addLineToPoint:[mytouch locationInView:self]];
        [self setNeedsDisplay];

    }
YogiAR
  • 2,207
  • 23
  • 44
2

Drawing only happens inside a method called -drawRect: (which is automatically called when a view is marked as needing display via setNeedsDisplay). So a drawRect:withBezierPath: method will never get invoked automatically. The only way it will execute is if you call it yourself.

Once you have a UIBezierPath, however, it's very easy to draw it:

- (void)drawRect:(CGRect)rect {
  UIBezierPath *path = ...; // get your bezier path, perhaps from an ivar?
  [path stroke];
}

There's no need to futz around with Core Graphics if all you want to do is draw a path.

Dave DeLong
  • 242,470
  • 58
  • 448
  • 498