objective-c - -setNeedsDisplay 未被调用以刷新 drawRect

标签 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。

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

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

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

最佳答案

重复我在评论中所说的,你遇到的问题是你的 UIView 子类对象在 drawRect 调用被执行之前被释放,这意味着无论持有对对象的引用,在本例中是您的 Controller ,在您打算之前释放它,使用 ARC 有时会出现一些小问题。

在包含此 View 的 Controller 代码中,您应该声明如下内容:

@property (weak, nonatomic) IBOutlet Schedule *scheduleView;

并合成:

@synthesize scheduleView = _scheduleView;

并且在 Controller 的dealloc方法中:

self.scheduleView = nil;

如果您使用的是 Storyboard,但自从您为此创建了一个 .xib 文件后您似乎没有使用它,您应该正确连接它。如果不是简单地实例化它并分配它。

扩展我之前所说的内容,我不确定您要做什么,但是看看您的代码,您正在创建 View 的一小段时间,当通知被调用时,它就在那里被释放,因为没有人持有它的引用。通过执行我所说的操作并按住 control+click 从 Controller 拖动到界面构建器中的 View 并将其连接起来,它将保存对它的引用,并且您将只创建 1 个 Schedule 对象。

之后你必须修改你的代码以使用这个 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:&currentSelectDate length:sizeof(CFGregorianDate)];

        [self.scheduleView calendarTouched:currentSelectDate];
    }

    return;

}

如果您不使用界面构建器来设置所有内容,您还有另一个选择是 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 ];

}

最后一点,考虑到您是 iOS 开发的新手(我们都是),您可以转到 iTunes 并在 iTunes U 上查找斯坦福大学的 iPad 和 iPhone 开发类(class) (CS193P),它是完全免费的,它会教授您了解在 iOS 中进行开发所需了解的大部分内容。

关于objective-c - -setNeedsDisplay 未被调用以刷新 drawRect,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11217310/

相关文章:

ios - 为 NSURLSession 设置委托(delegate)并对其进行单元测试

objective-c - PackageMaker 的麻烦

ios - xcode 6.1 iOS 8.1 NSLocale displayNameForKey NSLocaleIdentifier 返回 nil

ios - 什么时候可以通过将代码放在 AppDelegate 中来减少代码重复?

ios - 如何将固定大小的 UIView 添加到 UIStackView?

iphone - UIDatePicker 不显示适当的时间

ios - 如何在ios中为多个 View 创建相同的计时器?

ios - React-native - 由于双重转换导致构建失败

ios - 检查互联网连接时,隐藏的 UIVIEW 无法快速工作

iphone - DidFinishLoading View 更改