0

Important:

I had figured out the problem but a moderator deleted it for some reason:

I tried calling the function directly from the button instead of having the function in the view controller.

I still don't fully understand why it didn't work, so I will accept any answer to that question.

Main Post

I am trying to do some drawing after pressing a UIButton. My drawing is done in a subclass of UIView. I have an instance of this subclass in my ViewController. I also have a UIButton in my ViewController that calls a function of the subclass. In that function I call

[self setNeedsDisplay];

When I load up my app, drawRect is called once at the when the view loads, but is never called again, although setNeedsDisplay is being called every time the button is pressed. I looked at many similar questions and I have not found a solution.

I will post all of my code here:

AEViewController.h

#import <UIKit/UIKit.h>
#import "AEGraphView.h"

@interface AEViewController : UIViewController{

IBOutlet AEGraphView *theView;

}
-(IBAction)updateAEGraphView:(id)sender;
@end

AEViewController.m

#import "AEViewController.h"

@interface AEViewController ()

@end

@implementation AEViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    theView = [[AEGraphView alloc] init];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
    } 
    else {
        return YES;
    }
}
-(IBAction)updateAEGraphView:(id)sender{
    [theView UpdateView];
}

@end

AEGraphView.h

#import <UIKit/UIKit.h>

@interface AEGraphView : UIView{
    
    
    CGContextRef mainContext;
    int power;
    int multiplier;
    
    
}
-(void)prepareGraphics;
- (void) drawLineFrom:(CGPoint)p1 To:(CGPoint)p2;
-(void)UpdateView;
@end

AEGraphView.m

#import "AEGraphView.h"

@implementation AEGraphView

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


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    [self prepareGraphics];
    // Drawing code
    NSLog(@"called");
    if (power == 0) {
        [self drawLineFrom:CGPointMake(100,100) To:CGPointMake(-50, -2)];
    }
    else {
        [self drawLineFrom:CGPointMake(0, 0) To:CGPointMake(150, 150)];
    }
    [super drawRect:rect];
    
}

-(void)prepareGraphics{
    mainContext = UIGraphicsGetCurrentContext();
    CGContextSetShouldAntialias(mainContext, TRUE);
    CGContextSetLineWidth(mainContext, 2);
    CGContextSetLineCap(mainContext, kCGLineCapRound);
    
}
- (void) drawLineFrom:(CGPoint)p1 To:(CGPoint)p2{
    NSLog(@"%f,%f  to %f,%f", p1.x,p1.y,p2.x,p2.y);
    // Begin a path.
    CGContextBeginPath(mainContext);
    
    // Add a line to the path.
    CGContextMoveToPoint(mainContext, p1.x, p1.y);
    CGContextAddLineToPoint(mainContext, p2.x, p2.y);
    
    // Stroke and reset the path.
    CGContextStrokePath(mainContext);
}
-(void)UpdateView{
    if (power == 0) {
        power = 1;
    }
    else {
        power = 0;
    }
    [self setNeedsDisplay];
}
@end
Community
  • 1
  • 1
WolfLink
  • 3,308
  • 2
  • 26
  • 44
  • Do make sure that your view is visible because `-drawRect` won't fire if it isn't visible. – Vervious Jul 16 '12 at 02:18
  • It was nothing basic like not being visible, outlet not set, typo, etc. It was that drawRect won't get called if the IBAction function that ends in a call to setNeedsDisplay is called from a different class, even though setNeedsDisplay is called. The question now is why does the IBAction need to be sent directly to AEGraphView? – WolfLink Jul 16 '12 at 02:26
  • 1
    Then the IBAction must and should work the same way every time (it being the equivalent of a void type function). Double check nielsbot's answer, because `theView = [[AEGraphView alloc] init];` looks suspicious (it should already be inited/extant if the IBOutlet is connected properly) and would replace the view reference with a reference to a new one that's not visible and won't have drawRect called. Try `NSLog("%@", self)` to see if you're triggering the methods on the right instance of your UIView class, because it doesn't look like it. – Vervious Jul 16 '12 at 22:55
  • Deleted all of the [[Object alloc] init]'s I had in my program as all of them were connected in interface builder and it worked! thanks! – WolfLink Jul 16 '12 at 23:27

2 Answers2

1

Solution was having the function called from the button instead of called from a function in the view controller that was called by the button.

WolfLink
  • 3,308
  • 2
  • 26
  • 44
0

Are you sure your outlet that points to your custom UIView is hooked up? Check if it's nil. Also, did you verify your function is being called?

nielsbot
  • 15,922
  • 4
  • 48
  • 73
  • The view is set, I have it draw something when it is first called and it should draw something else if it is called again. – WolfLink Jul 15 '12 at 23:06
  • I have an NSLog in the function that calls setNeedsDisplay, an NSLog in setNeedsDisplay itself, and an NSLog in drawRect. The NSLog in drawRect is called once, all the other NSLog's are called every time the button is pressed. – WolfLink Jul 15 '12 at 23:07
  • are you calling `super` in both `-setNeedsDisplay` and `-drawRect`? – nielsbot Jul 15 '12 at 23:33
  • Yes I am calling super in both. – WolfLink Jul 15 '12 at 23:37