2

I'm trying to append a string to the view with the drawAtPoint:point withAttributes:attrs method, but the string is not to be seen anywhere inside the view, or at least I cannot see it (it might be that the color is the same as the view, white).

The following code is what I use in the viewDidLoad of my view controller:

NSMutableDictionary *stringAttributes = [[NSMutableDictionary alloc] init];


[stringAttributes setObject:[UIColor redColor]forKey: NSForegroundColorAttributeName];


NSString *someString = [NSString stringWithFormat:@"%@", @"S"];

[someString drawAtPoint:CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2) withAttributes: stringAttributes];

What is it that I'm doing wrong ?

EDIT: After following @rokjarc's suggestions, I have created a view controller with a drawRect method that adds the string to the current context:

#import <Foundation/Foundation.h>


@interface XYZSomeView : UIView
@end

#import "XYZSomeView.h"
#import "NSString+NSStringAdditions.h"


@implementation XYZSomeView

- (void)drawRect:(CGRect)rect {

    [super drawRect:rect];

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);

    NSMutableDictionary *stringAttributes = [[NSMutableDictionary alloc] init];


    [stringAttributes setObject:[UIColor redColor]forKey: NSForegroundColorAttributeName];


    NSString *someString = [NSString stringWithFormat:@"%@", @"S"];

    [someString drawAtPoint:CGPointMake(rect.origin.x, rect.origin.y) withAttributes: stringAttributes];

    NSLog(@"%@", someString);

    CGContextRestoreGState(context);
}

@end

And inside my root view controller I init the XYZSomeView:

#import "XYZRootViewController.h"
#import "XYZSomeView.h"


@implementation XYZRootViewController
- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor whiteColor];



    XYZSomeView *someView = [[XYZSomeView alloc] init];

    [self.view addSubview:someView];

}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];

    NSLog(@"%@", @"XYZRootViewController reveived memory warning");
}
@end

The issue is that my drawRect is not called, is that because I have to call it myself ? I thought that this method should be called upon initialization without me having to call it.

Roland
  • 9,321
  • 17
  • 79
  • 135
  • Try moving it to `viewWillAppear` as the layout of the views is not complete during `viewDidLoad` so the `CGPointMake` method may not be returning the location you are expecting. – bobnoble Nov 02 '13 at 12:58
  • @rolandjitsu: You have to set some frame to the someView. For start it can be as simple as `someView.frame = self.view.bounds;` And i would coment-out the `[super drawRect:rect];` Also try setting some fixed coordinates for first attempts - drawing at the origin of rect is not a good idea since theoretically rect can be anything - it gives you the area of the view that needs to be redrawn. – Rok Jarc Nov 02 '13 at 14:38
  • Ok, so I should use `initWithFrame` instead of `init`. I forgot that `XYZSomeView` is not a subclass of `UIViewController`. Could you elaborate why I should not call the super `drawRect` ? I have read that is a good thing to call the super methods before going on with my own, but maybe I'm wrong since I'm new to this. – Roland Nov 02 '13 at 14:59
  • True, usually it is good to call super methods when overriding. There are couple of exemptions: you don't call `[super loadView];` when subclassing `UIVIewController`. And with `[super drawRect]` - when it's not needed it just extends the time for your custom drawRect to execute. It might be needed when you add subviews to your custom view - not sure on this one. – Rok Jarc Nov 02 '13 at 15:09
  • I see, I'll try to see if I can find more info on when I should and when I shouldn't super calls. And your suggestions worked, I now can see the string and the upppercasing that I have implemented in a category it works. Thanks for the help :) – Roland Nov 02 '13 at 15:12

1 Answers1

2

You will need a reference to current graphics context in order to use this function: docs. You don't have this reference within viewDidLoad:. Usually this is done within drawRect:. There are ways to use it while generating a content off screen - but this doesn't seem to fit your needs.

If you want to add a simple text to a view controller in its' viewDidLoad consider adding simple UILabel with transparent background to the view of this view controller.

Rok Jarc
  • 18,765
  • 9
  • 69
  • 124
  • I usually use labels, but in this case I'm learning how to use categories and how to extend the existing frameworks with new methods. I'm trying to add a drawAtPoint methods that uppercases the string before adding it to the view. That us the only reason why I do it this way. – Roland Nov 02 '13 at 13:02
  • Aha. For learning case you might want to try subclassing `UIView` and overriding it's `drawRect` method. – Rok Jarc Nov 02 '13 at 13:03
  • One good example on how to achieve this is here: http://stackoverflow.com/a/10293425/653513 – Rok Jarc Nov 02 '13 at 13:05
  • And here is a short discussion on the exact same problem: http://stackoverflow.com/a/6893879/653513 `viewDidLoad:` is not the place for trying out functions that use `CGContext` as a reference. – Rok Jarc Nov 02 '13 at 13:08
  • Cool, so because I don't want to mess with my root view controller drawRect, I'll just create a new view controller and add as subview to my root view controller. I'll also use the drawRect as you suggested and I hope it'll work. One questions though, should I call the super drawRect before having my own code inside my custom drawRect ? – Roland Nov 02 '13 at 13:11
  • Exactly! Your `viewController` doesn't even have a `drawRect:` - it's `view` has it. It's not necessary to call the `super` - i think you'll have to take care of drawing the background (if you need it) your self in this case. – Rok Jarc Nov 02 '13 at 13:18