-setNeedsDisplay未被调用以刷新drawRect

时间:2012-06-26 23:21:12

标签: objective-c ios uiview uikit

我有两种方法可以从-drawRect:

中调用
- (void)drawRect:(CGRect)rect  {

    if(drawScheduleFlag) {
        [self drawSchedule];
        drawScheduleFlag = false;
    }
    else
        [self drawGrid];
}
在初始化时调用

-drawGrid。从该代码调用另一个方法(-drawSchedule),该代码位于主线程上:

- (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;
}

我知道代码正在执行,但没有任何条件来绘制日程安排。为什么-[self setNeedsDisplay]没有导致-drawRect被调用?

更新:我已经休息了所以我很肯定它没有被调用。原始网格被绘制一次;当用户点击日历日期时,调用-calendarTouched并完全执行。 drawScheduleFlag设置为true,并调用 - [self setNeedsDisplay],但-drawRect不调用。似乎UIView没有失效(-setNeedsDisplay应该这样做),因此不会调用-drawRect。

UPDATE#2:我有一个带有两(2)个UIViews的UIViewController的.xib。第一个UIView占据了大约1/3的iPad屏幕,第二个UIView占据了屏幕的底部2/3。每个UIView都有自己的特定类;顶部UIView显示日历并正常工作,捕捉触摸并更改所选日期。

底部的UIView应该显示在顶部UIView中选择的日期的时间表。这就是问题所在。由于顶级UIView正在工作,我将提出底部UIView类的代码。它首先在首次调用-drawRect时绘制调度网格。一旦用户选择了一天,就应该使UIView无效以在网格上绘制实际的时间表。

以下是Schedule.h的代码:http://pastebin.com/NQpj0i07 以下是Schedule.m的代码:http://pastebin.com/YBbE8y0T 以下是控制器的代码:http://pastebin.com/nDqBCivj 请注意,两个pastebin都将在6月28日太平洋标准时间下午5点38分24小时后到期

1 个答案:

答案 0 :(得分:2)

重复我在评论中所说的,你遇到的问题是你的UIView子类对象在执行drawRect调用之前被释放了,这意味着无论是什么持有对@property (weak, nonatomic) IBOutlet Schedule *scheduleView; 调用的引用对象,在这种情况下,你的控制器,在你的意思之前释放它,有时候会出现使用ARC的小问题。

在拥有此视图的控制器代码中,您应该声明这样的内容:

@synthesize scheduleView = _scheduleView;

并合成:

dealloc

在控制器的self.scheduleView = nil; 方法中:

- (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:&currentSelectDate length:sizeof(CFGregorianDate)];

        [self.scheduleView calendarTouched:currentSelectDate];
    }

    return;

}

如果您正在使用故事板,因为您为此创建了.xib文件,而您似乎没有使用它,您应该正确连接它。如果不是简单地实例化并分配它。

扩展我之前所说的内容,我不确定你要做的是什么,但是看看你的代码,你会在通知被调用时短暂创建视图,然后它就会被解除分配没人提到它。通过执行我所说和控制的操作+单击从控制器拖动到界面构建器中的视图并将其挂起,它将保留对它的引用,并且您将只创建1个Schedule对象。

之后,您将不得不修改您的代码以使用此计划实例:

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 ]; } 中的以下内容:

{{1}}

作为最后一点,考虑到你是iOS开发的新手(就像我们一样)你可以去iTunes并在iTunes U上寻找斯坦福的iPad和iPhone开发课程(CS193P),它是完全免费的,它会教您在iOS中开发所需的大部分内容。