我正在研究一個iPad應用程序,該應用程序具有用於滾動瀏覽數據的滑塊。滾動時,顯示地圖並更新數據。問題是,如果你滾動得足夠快(或以某種方式觸發競爭條件),應用程序崩潰訪問殭屍NSString。我已經能夠跟蹤它在探查,發現這個:應用程序在繪製UILabel時崩潰 - 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:]
我使用ARC上的iOS5,所以我在保留/釋放的控制是根本。即使我是,看着上述,這是正確的。問題似乎是繪圖函數和實際更改的UILabel字符串之間的競爭條件。 UILabel釋放第一個字符串,因爲已經設置了一個新的字符串,但繪圖函數以某種方式持有對它的引用,但沒有保留它。
作爲說明,我沒有以任何方式修改UILabel。
任何想法?
---代碼添加更新:
滑塊更新:
-(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];
}
setYear:
-(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]];
}
setToMap:
個-(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];
}
updateVotes:
-(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];
}
}
請包括你在哪裏更新數據作爲滑塊值發生變化的代碼創建字符串。請記住,如果滑塊是連續的,則可以每秒調用數百次。 – jrturton
這是否有任何線程?上面顯示的內容不應該像你描述的那樣行爲,在繪製之前將字符串釋放,除非在另一個地方有一個不同的線程將地毯拉出。我不知道只有一個線程涉及到這種競爭條件。 –