objective-c - 应用程序在绘制 UILabel 时崩溃 - NSString 是僵尸

标签 objective-c ios automatic-ref-counting

我正在开发一个 iPad 应用程序,它有一个用于滚动数据的 slider 。滚动时,会显示 map 并更新数据。问题是,如果您滚动得足够快(或以某种方式触发竞争条件),应用程序会在访问僵尸 NSString 时崩溃。我已经能够在探查器中找到它并找到了这个:

Event Type  RefCt   Timestamp       Size    Responsible Library     Responsible Caller
Malloc      1       01:55.166.466   16      Foundation              -[NSPlaceholderString initWithFormat:locale:arguments:]
Autorelease <null>  01:55.166.472   0       Foundation              +[NSString stringWithFormat:]
CFRetain    2       01:55.166.473   0       My Program              -[StateView updateVotes:]
CFRetain    3       01:55.166.476   0       UIKit                   -[UILabel setText:]
CFRelease   2       01:55.166.504   0       My Program              -[StateView updateVotes:]
CFRelease   1       01:55.177.661   0       Foundation              -[NSAutoreleasePool release]
CFRelease   0       01:55.439.090   0       UIKit                   -[UILabel setText:]
Zombie      -1      01:55.439.109   0       UIKit                   -[NSString(UIStringDrawing) drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:]

我在 iOS5 上使用 ARC,所以我根本无法控制保留/释放。即使我是,看上面的,这是正确的。问题似乎是绘图函数和实际更改的 UILabel 字符串之间的竞争条件。 UILabel 释放第一个字符串,因为已经设置了一个新字符串,但是绘图函数以某种方式持有对它的引用,但没有保留它。

请注意,我没有以任何方式修改 UILabel。

有什么想法吗?

--- 作为更新添加的代码:

slider 更新:

-(void)sliderValueChanged:(UISlider *)slider {
    float position = slider.value - 1790.0f;
    int year;
    if(position <= 0.0f) {
        year = 1789;
    } else {
        year = 1792 + (floor(position / 4.0f)*4);
    }
    [self setYear:year];
}

设置年份:

-(void)setYear:(int)year {
if (year == currentYear) {
        // year didn't change, so don't do anything
        return;
    }

    [yearLabel setText:[[NSString alloc] initWithFormat:@"%i", year]];
    currentYear = year;

    [self getMapForYear:year];
}

getMapForYear:

-(void) getMapForYear:(int)year {
    [self setToMap:[historicalData objectForKey:[NSNumber numberWithInt:year]];
}

设置 map :

-(void) setToMap:(HistoricalMap *)map {
    // Label the map
    for (State *state in [map states]) {
        [mapController setVotes:[state votes] forState:[state abbreviation]];
    }
}

setVotes:forState:

-(void)setVotes:(NSNumber *)votes forState:(NSString *)stateAbbreviation {

    StateView *state = [states objectForKey:stateAbbreviation];
    if (state == nil) {
        NSLog(@"Invalid State Votes -- %@", stateAbbreviation);
        return;
    }
    [state updateVotes:votes];
    [state setNeedsDisplay];
}

更新投票:

-(void)updateVotes:(NSNumber *)newVotes {
    [self setVotes:newVotes];

    NSString *voteString = [[NSString alloc] initWithFormat:@"%@", newVotes];

    [voteLabel setText:voteString];
    if ([newVotes isEqual:[NSNumber numberWithInt:0]]) {
        [[self voteLabel] setHidden:YES];
        [[self stateAbbreviationLabel] setHidden:YES];
    } else {
        [[self stateAbbreviationLabel] setHidden:NO];
        [[self voteLabel] setHidden:NO];
    }
}

最佳答案

我认为您在 slider 移动期间试图做的事情太多了。单独创建和执行核心数据获取请求似乎有点矫枉过正,更不用说更新整个 GUI 和一屏标签了。您是否在设备上测试过它的性能?

分析这些代码部分并查看时间花在了哪些地方可能是值得的。例如,您可以考虑缓存获取请求或结果,或者您可能必须仅在 slider 停止时或仅针对路径上的每个 n 增量才求助于更新。

关于objective-c - 应用程序在绘制 UILabel 时崩溃 - NSString 是僵尸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8217779/

相关文章:

ios - 变量总是按值传递

ios5 - dyld`dyld_fatal_error(iOS上不兼容的api)的原因是什么?

objective-c - 为 NSXMLParser 设置委托(delegate),给出 SIGABRT 错误

objective-c - 为什么 Clang 在没有 return 语句的 block 中被 @try{} 混淆了?

ios - 继承 MKAnnotationView 并从 initWithFrame : overloads 调用 init 时无限循环

swift - ARC weak var Swift(不是闭包)

ios - 使用 ARC Over Release 进行 NSDate 内存管理

objective-c - 在 Objective-C 应用程序之间传递参数

ios - 返回按钮对应错误的导航 Controller

ios - NSPredicate 使用数组作为过滤器