4
votes

I am fairly new to swift, and I had been doing all of my coding programmatically. I finally branched out and started learning some awesome things using the Interface Builder and what not.

I have created some cool custom drawings in a UIView class I created using the drawRect(rect: CGRect) function, and now I want to be able to call that class multiple times in a loop to layout in my view. Whenever I try to instantiate the view programmatically, it seems as though drawRect is not getting called. I'm not getting any errors, just nothing is drawing. Here is my code for laying out the custom view, where TesterView is my custom UIView subclass that performs the custom drawing:

func testView() {

    let testerView:TesterView = TesterView()
    self.view.addSubview(testerView)
    testerView.translatesAutoresizingMaskIntoConstraints = false
    let height = NSLayoutConstraint(item: testerView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 200)
    let width = NSLayoutConstraint(item: testerView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 200)
    let centerX = NSLayoutConstraint(item: testerView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)
    let bottom = NSLayoutConstraint(item: testerView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)
    self.view.addConstraints([height, width, centerX, bottom])


}

Any and all help would be greatly appreciated. I didn't start trying to call the view in a loop yet because I can't even get it to work once. What I need to do eventually is loop through and instantiate the class multiple times.

1

1 Answers

13
votes

You don't call drawRect: explicitly. Instead, you set the needsDisplay property to YES.

From the View Programming Guide: Creating a custom view

The most common way of causing a view to redisplay is to tell it that its image is invalid. [...] NSView defines two methods for marking a view’s image as invalid: setNeedsDisplay:, which invalidates the view’s entire bounds rectangle, and setNeedsDisplayInRect:, which invalidates a portion of the view.

From the UIView Class Reference

When the actual content of your view changes, it is your responsibility to notify the system that your view needs to be redrawn. You do this by calling your view’s setNeedsDisplay or setNeedsDisplayInRect: method of the view.

- (void)drawRect:(CGRect)rect
[...]
You should never call this method directly yourself. To invalidate part of your view, and thus cause that portion to be redrawn, call the setNeedsDisplay or setNeedsDisplayInRect: method instead.

You implement the drawing in drawRect: and then call [myView setNeedsDisplay:YES] when you need to redraw the view (e.g. for games, in a loop).