Reputation: 4984
I have two methods that get called from within -drawRect:
- (void)drawRect:(CGRect)rect {
if(drawScheduleFlag) {
[self drawSchedule];
drawScheduleFlag = false;
}
else
[self drawGrid];
}
-drawGrid
is called at initialization time. The other method (-drawSchedule
) is called from this code, which is on the main thread:
- (void) calendarTouched: (CFGregorianDate) selectedDate {
// NSLog(@"calendarTouched - currentSelectDate: %d/%d/%d", selectedDate.month, selectedDate.day, selectedDate.year);
// NSLog(@"Main thread? %d", [NSThread isMainThread]);
// get data from d/b for this date (date, staff name, cust name, time, length, services required)
//------ stub -------
scheduledDate.year = 2012;
scheduledDate.month = 6;
scheduledDate.day = 20;
staffName = @"Saori";
custName = @"Brian";
startTime.hour = 11;
duration = 2;
servicesReqd = @"Nails";
drawScheduleFlag = true;
[self setNeedsDisplay];
return;
}
I know the code is being executed, but nothing happens to draw the schedule. Why is -[self setNeedsDisplay]
not causing the -drawRect
to be called?
UPDATE: I have put breaks in so I'm positive it's not being called. The original grid is drawn once; when the user taps a calendar date, -calendarTouched is called and completely executed. The drawScheduleFlag is set to true, and -[self setNeedsDisplay] gets called, but -drawRect does not. It appears that the UIView is not being invalidated (which -setNeedsDisplay is supposed to do), therefore -drawRect is not called.
UPDATE #2: I have a .xib for a UIViewController with two (2) UIViews in it. The first UIView takes about 1/3 of an iPad screen, the second UIView takes the bottom 2/3 of the screen. Each UIView has it's own specific class; the top UIView displays a calendar and is working correctly, capturing touches and changing the date selected.
The bottom UIView is supposed to show the schedule for the date picked in the top UIView. This is where the problem is. Since the top UIView is working, I will put up the code for the bottom UIView's class. It basically draws the schedule grid when -drawRect is first called. Once the user has selected a day, it is supposed to invalidate the UIView to draw the actual schedule on the grid.
Here is the code for Schedule.h: http://pastebin.com/NQpj0i07 Here is the code for Schedule.m: http://pastebin.com/YBbE8y0T Here is the code for the controller: http://pastebin.com/nDqBCivj Note that both pastebin's expire in 24 hours from Jun 28, 5:38 PM PST
Upvotes: 1
Views: 2931
Reputation: 5836
Repeating what I said in the comments, the problem you are having is that your UIView
subclass object is getting deallocated before the drawRect
call gets executed, which means that whatever is holding the reference to the object, in this case your controller, is releasing it before you mean to, little issue that sometimes comes up with using ARC.
In the controller code that holds this view you should have something like this declared:
@property (weak, nonatomic) IBOutlet Schedule *scheduleView;
And synthesized:
@synthesize scheduleView = _scheduleView;
And in the controller's dealloc
method:
self.scheduleView = nil;
If you're using storyboards, which you appear to not be using since you made a .xib file for this, you should have it hooked up properly. If not simply instantiate it and assign it.
Expanding on what I said before, I'm not sure what you're trying to do but taking a look at your code you are creating the view for a brief moment when the notification gets called and right there it's getting deallocated because no one is holding a reference to it. By doing what I said and control+click drag from the controller to the view in interface builder and hooking it up it will hold the reference to it, and you'll only have 1 Schedule object created.
After that you'll have to modify your code to work with this instance of Schedule:
- (void) testNotification:(NSNotification *) notification {
// was the calendar tapped?
if ([[notification name] isEqualToString:@"calendarUpdated"]) {
NSDictionary *passedData = notification.userInfo; // get passed data
CFGregorianDate currentSelectDate;
NSData *data = [passedData objectForKey:@"currentSelectDate"];
[data getBytes:¤tSelectDate length:sizeof(CFGregorianDate)];
[self.scheduleView calendarTouched:currentSelectDate];
}
return;
}
The other option you have if you're not using interface builder to set everything up is the following in your viewDidLoad
:
- (void)viewDidLoad
{
[super viewDidLoad];
self.scheduleView = [[Schedule alloc] init];
[self.view addSubView:self.scheduleView]; // Probably some extra code for positioning it where you want
// notify me when calendar has been tapped and CFGregorianDate has been updated
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(testNotification:) name:@"calendarUpdated" object:nil ];
}
As a final note, considering you're new to iOS development (as we all were) you can go to iTunes and look for Stanford's iPad and iPhone Development course (CS193P) on iTunes U, it's completely free and it will teach you most of what you need to know for developing in iOS.
Upvotes: 2