Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Drawing with Xib file present

I have a view that I want to add some custom drawing to.

I know how to do this with a View that isn't connected to a Nib/Xib file

  • you write the drawing code in the -drawRect: method.

But if I init the view using

[[MyView alloc] initWithNibName:@"MyView" bundle:[NSBundle mainBundle]];

-drawRect: of course doesn't get called. I tried doing the below code in -viewDidLoad

CGRect rect = [[self view] bounds];

CGContextRef ref = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(ref, 2.0);
CGContextSetRGBStrokeColor(ref, 1.0, 1.0, 1.0, 1.0);
CGContextSetRGBFillColor(ref, 0, 0, 0, 0);
CGContextAddRect(ref, CGRectMake(1, 1, rect.size.width - 10, rect.size.height - 10));
CGContextStrokePath(ref);
CGContextDrawPath(ref, kCGPathFillStroke);

But nothing get drawn. Any ideas?

like image 728
JamesSugrue Avatar asked Nov 28 '25 22:11

JamesSugrue


2 Answers

I think the issue is that you're treating a view and its view controller as interchangeable. For example, there's no -[UIView initWithNibName:bundle:] method — that's a UIViewController method.

Furthermore, a view isn't really like a "canvas" for drawing. A view will be asked to draw itself; in general, it won't be drawn into from "outside."

So:

  1. Rename your subclass of UIViewController from MyView to MyViewController.

  2. Create a new UIView subclass named MyView.

  3. Add a -drawRect: method to your new MyView class that does the drawing you want.

  4. Finally, set the Custom Class of your view controller's view in Interface Builder to MyView using the Identity Inspector.

For example, you should be able to use this for your -[MyView drawRect:] implementation:

- (void)drawRect:(CGRect)rect {
    CGRect bounds = [[self view] bounds];

    CGContextRef ref = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(ref, 2.0);
    CGContextSetRGBStrokeColor(ref, 1.0, 1.0, 1.0, 1.0);
    CGContextSetRGBFillColor(ref, 0, 0, 0, 0);
    CGContextAddRect(ref, CGRectMake(1, 1, bounds.size.width - 10, bounds.size.height - 10));
    CGContextStrokePath(ref);
    CGContextDrawPath(ref, kCGPathFillStroke);
}

The drawing will be clipped to the update rectangle passed in.

like image 66
Chris Hanson Avatar answered Nov 30 '25 12:11

Chris Hanson


Here are three possible solutions, depending on your constraints.

  1. Set the class of the NSView object in the Xib file to be one of your custom classes. You mention that you know how to do custom drawing with a "hard-coded" NSView subclass, and this would work the same way. When the Xib file is loaded, the NSView is loaded into memory as an object of your custom class instead of the default. Changing the class type of the view in the Xib is simple with Interface Builder.
  2. If the NSView object in the Xib file is already some kind of custom view that you do not want to override, you can add a subview to that view in Interface Builder, and simply make the subview into a custom class of your design (as in #1)
  3. You can programmatically add a subview to the NSView object in the Xib file at runtime. In your sample code above, you could create an instance of your own custom NSView subclass, and then add it to the existing view using the addSubView: method.
like image 31
e.James Avatar answered Nov 30 '25 12:11

e.James



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!