2

To get a sense of what I'm doing without posting pages of code... I have an NSOperation that I'm using to process files as they are added to a folder. In that NSOperation I'm using the NSNotificationCenter to send notifications to an NSView whenever a new job is started. The idea is, that I want to add a new subview to give me some information about the job that just started. The problem is I can't seem to get new subviews to draw. Here is what I have right now.

- (void)drawRect:(NSRect)dirtyRect
{
    NSLog(@"Draw Count %i", [jobViewArray count]);
    int i = 0;
    while (i < [jobViewArray count]) {
        [self addSubview:[jobViewArray objectAtIndex:i]];
    }    

}

and then further down:

-(void) newJobNotification: (NSNotification *) notification
{
    if (!jobViewArray)
            jobViewArray = [[NSMutableArray alloc] init];
    ++jobCount;
    NSRect rect;
    rect.size.width = 832;
    rect.size.height = 120;
    NSPoint point = { 0, ((jobCount * 120) - 120) };
    rect.origin = point;
    ProgressView *newJob = [[ProgressView alloc] initWithFrame:rect];

    [jobViewArray addObject:newJob];    
    NSLog(@"Notice Count %i", [jobViewArray count]);

    }

}

When I use my app to add a job, the notification is properly received by my NSView, the subview is properly added to the jobViewArray, but then when drawRect: gets called again my jobViewArray is empty. It's the first time I've tried to do something like this so I'm probably doing something completely wrong here... I guess that goes with out saying since it doesn't work huh?

Kris
  • 349
  • 1
  • 2
  • 13
  • Does your log statement for the jobViewArray count in the notification show what you would expect? is jobViewArray a property? – sosborn Jul 12 '11 at 22:44
  • Yes, in the notification method the log statement returns a count of 1, but then later in drawRect is returns 0. jobViewArray is a property with the following definition `@property (readwrite, copy) NSMutableArray *jobViewArray;` – Kris Jul 12 '11 at 23:27
  • In the notification put that log statement at the top. Where it is now it will always return at least one because if you don't a jobViewArray you create one anyway. Also, iain is right, you shouldn't be adding views in drawRect. – sosborn Jul 13 '11 at 01:11
  • If I add a log statement after the jobViewArray is created the count returns 0 because I haven't added any items to the array yet. The one after the nsview is added to the array returns 1. – Kris Jul 13 '11 at 15:14

1 Answers1

1

You shouldn't be adding the subview to the view in drawRect:. When you receive the notification you should add the subviews there because the second time the notification comes around, you're going to add 2 subviews, then the next time 3 subviews and so one.

If you add the subview in the notification then you'll not need to mess around with the array.

iain
  • 5,660
  • 1
  • 30
  • 51
  • I was trying to add it to drawRect: because I read somewhere you shouldn't draw views outside of drawRect:. I actually want a new subview every time the notification is called. For updates to the subview I was going to have a separate notification. I went ahead and put a `[self addSubview: newJob]` in the notification... but it still doesn't draw the subview. I know the code for the subview works because if I manually put it into the drawRect: it does add the subview to the window as soon as it opens. – Kris Jul 13 '11 at 15:18
  • OK, additional information. I got rid of my jobViewArray. In my notification I now have `[self addSubview:newJob]` and then a `NSLog(@"After Count %i", [[self subviews] count])` which tells me I have 1 subview. When I call the same log statement in the drawRect: it sells me I have 0 subviews. I don't understand why my subviews are disappearing between my notification and the drawRect:... – Kris Jul 13 '11 at 15:47
  • When you call addSubview: it isn't drawing the subview, it is just adding it to the parent view. The subview will get its own call to drawRect: when it needs to draw. Is your notification being called from a separate thread or anything? If it is, you may need to use [self performSelectorOnMainThread:withObject:waitUntilDone:] and create a new method that does the actual addSubview: call – iain Jul 13 '11 at 18:55
  • OK, I don't know what I had wrong before... but I basically trashed my subclass and rewrote it pretty much just like I had it and it works now... I did make some changes based on the comments here, but when I rewrote is it was essentially the same code as what was in the one that didn't work. Go figure! – Kris Jul 13 '11 at 19:06