1

I'm trying to draw text in a UIView, 'erase' it, then draw it again in a different position. (Or draw different text instead)

I've got a Single Page App, Storyboard, Xcode 5, iOS 7. I've created a subclass for the UIView and can draw a single string one time using the 'drawRect' method. However, this only gets called once so it's not useful.

I've created another method in my subclass, but calling it doesn't seem to work.

How can I create a method that I can call repeatedly to draw the text?

Here's my code: MyView.h

#import <UIKit/UIKit.h>

@interface MyView : UIView

-(void)drawIt:(NSString *)inText;
@end

MyView.m

#import "MyView.h"

@implementation MyView

- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

// This executes once and works
-(void)drawRect:(CGRect)myRect{
    UIFont *myFont=[UIFont fontWithName:@"Helvetica" size:30];
    NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
    paragraphStyle.alignment = NSTextAlignmentLeft;

    NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
    [attributes setObject:myFont forKey:NSFontAttributeName];
    [attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
    [attributes setObject:[UIColor blackColor] forKey:NSForegroundColorAttributeName];
    [@"TEST"  drawInRect:myRect withAttributes:attributes];
}

//This is what I'd like to call repeatedly with different text or clear, etc...
//However nothing shows when I call it
-(void)drawIt:(NSString *)inText{
    CGRect myRect=CGRectMake(0,0,self.bounds.size.width,self.bounds.size.height);
    UIFont *myFont=[UIFont fontWithName:@"Helvetica" size:30];

    NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
    paragraphStyle.alignment = NSTextAlignmentRight;

    NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
    [attributes setObject:myFont forKey:NSFontAttributeName];
    [attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
    [attributes setObject:[UIColor blackColor] forKey:NSForegroundColorAttributeName];
    [inText drawInRect:myRect withAttributes:attributes];
}
@end

And in my ViewController.m:

#import "TextDrawViewController.h"
#import "MyView.h"

@interface TextDrawViewController ()

@end

@implementation TextDrawViewController

- (void)viewDidLoad{
    [super viewDidLoad];

    MyView *xView = [[MyView alloc] init];

    [xView drawIt:@"junk"];
}
@end
rmaddy
  • 314,917
  • 42
  • 532
  • 579
wayneh
  • 4,393
  • 9
  • 35
  • 70

1 Answers1

1

It is better to place all drawing code to -(void)drawRect:(CGRect)myRect method.
After updating text and position call [self setNeedsDisplay]; and iOS automatically will call drawRect: method.

Vlad Papko
  • 13,184
  • 4
  • 41
  • 57
  • This leads me to two questions: 1) Why is this better? 2) How can I make the alternate method above "drawIt" work? – wayneh Apr 17 '14 at 17:56
  • @wayneh you can't draw anything at any time when you want. iOS decides it by itself when call drawRect method. You could only ask it to redraw view by calling setNeedsDisplay methods. It is so due drawing optimisations that iOS executes. [here](http://stackoverflow.com/questions/18521540/how-does-drawrect-and-cggraphicscontext-work) are more explanations. Regarding to your task: You could store all changing data (text, position and etc.) to instance variables, use it for drawing in drawRect method and call setNeedsDisplay method when one or more variables changed. Hope it will help to you. – Vlad Papko Apr 17 '14 at 20:18
  • Are you saying that I can't draw Text with my own method? That seems highly unlikely - how could anyone develop a drawing program? – wayneh Apr 17 '14 at 22:13
  • @wayneh, they develop a drawing program by putting their drawing code in drawRect as Visput says. That doesn't mean everything has to be done there -- you can, for instance, create a whole bunch of bezier paths outside draw rect, but then you need to stroke or fill them (i.e. actually do the drawing) in drawRect. The method that Visput outlines in his comment is the way to go. – rdelmar Apr 18 '14 at 05:35
  • @wayneh actually you could move call of drawIt method to drawRect method implementation and use setNeedsDisplay to initiate view redraw. – Vlad Papko Apr 18 '14 at 07:06
  • Wow. This is so totally different than any other OS I've worked with. Generally you can get the 'canvas' context from anywhere and do whatever. I can't believe iOS is so formal! Thanks for the clarification. Also, I found this which helps describe it too: https://developer.apple.com/library/ios/documentation/2ddrawing/conceptual/drawingprintingios/graphicsdrawingoverview/graphicsdrawingoverview.html – wayneh Apr 18 '14 at 12:22