【问题标题】:Crash after returning to tableview返回tableview后崩溃
【发布时间】:2012-01-16 14:08:22
【问题描述】:

所以我正在编写一个应用程序来读取 rss 提要,并在表格视图中显示内容。它还允许用户播放它为每个项目找到的 mp3。无论如何,在我开始添加新视图之前,该应用程序似乎运行良好。现在,每次我从视图返回并滚动一下时,我都会收到“程序收到信号“SIGABRT””或类似的信息。

这是程序的大部分内容:

- (IBAction)playAction:(id)sender
{
// Get row
UIButton *senderButton = (UIButton *)sender;
UITableViewCell *buttonCell = 
(UITableViewCell *) [[senderButton superview] superview];
NSInteger buttonRow = [[self.tableView 
                        indexPathForCell:buttonCell] row];

// Entry for row
RSSEntry *senderEntry = [_allEntries objectAtIndex:buttonRow];


// This is where _allEntries gets filled

- (void)requestFinished:(ASIHTTPRequest *)request {

[_queue addOperationWithBlock:^{

    NSError *error;
    GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:[request responseData]
                                                           options:0 error:&error];

    if (doc == nil) 
    {
        NSLog(@"Failed to parse %@", request.url);
    } 
    else 
    {

        NSMutableArray *entries = [NSMutableArray array];
        [self parseRss:doc.rootElement entries:entries]; 

        if ([_allEntries count] > 0) {

            [[NSOperationQueue mainQueue] addOperationWithBlock:^{

                // Update
                int i=0;
                while (![[[_allEntries objectAtIndex:i] articleUrl] isEqualToString:[[entries objectAtIndex:i] articleUrl]]) 
                {
                    [_allEntries insertObject:[entries objectAtIndex:i] atIndex:0];
                    i++;
                }
                [self.tableView reloadData];
            }];

        }
        else
        {
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{

                for (RSSEntry *entry in entries)
                {
                    [_allEntries addObject:entry];
                }

                NSLog(@"entries:%d", [_allEntries count]);
                [self.tableView reloadData];
            }];
        }


    }

}];



}
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"View did load");

self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] 
                                          initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh 
                                          target:self 
                                          action:@selector(refreshButton:)];

pauseImage = [UIImage imageNamed:@"pause_circle_small.png"];
playImage = [UIImage imageNamed:@"play_circle_small.png"];

player = nil;
isPlaying = NO;

self.title = @"Feed";
self.allEntries = [NSMutableArray array];
self.queue = [[[NSOperationQueue alloc] init] autorelease];
self.feed = [[NSString alloc] initWithString:@"http://site.org/rss/"];
[self refresh];
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [_allEntries count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";

UILabel *mainLabel, *secondLabel;
UIButton *playBtn;

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) 
{
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                   reuseIdentifier:CellIdentifier] autorelease];

    mainLabel = [[[UILabel alloc] initWithFrame:CGRectMake(42.0, 5.0, 250.0, 20.0)] autorelease];
    mainLabel.tag = MAINLABEL_TAG;
    mainLabel.font = [UIFont fontWithName:@"Arial-BoldMT" size:18.0];
    mainLabel.textAlignment = UITextAlignmentLeft;
    mainLabel.textColor = [UIColor blackColor];
    mainLabel.highlightedTextColor = [UIColor whiteColor];
    [cell.contentView addSubview:mainLabel];

    secondLabel = [[[UILabel alloc] initWithFrame:CGRectMake(42.0, 27.0, 250.0, 15.0)] autorelease];
    secondLabel.tag = SECONDLABEL_TAG;
    secondLabel.font = [UIFont fontWithName:@"ArialMT" size:14.0];
    secondLabel.textAlignment = UITextAlignmentLeft;
    secondLabel.textColor = [UIColor colorWithRed:222.0/255.0 green:95.0/255.0 
                                             blue:199.0/255.0 alpha:1.0];
    secondLabel.highlightedTextColor = [UIColor whiteColor];
    [cell.contentView addSubview:secondLabel];

    playBtn = [UIButton buttonWithType:UIButtonTypeCustom];

    playBtn.tag = PLAYBTN_TAG;
    playBtn.frame = CGRectMake(2.0, 6.0, playImage.size.width, playImage.size.height);
    [playBtn setBackgroundImage:playImage forState:UIControlStateNormal];
    //[playBtn setBackgroundImage:playImage forState:UIControlStateHighlighted];

    [playBtn addTarget:self action:@selector(playTapped:) 
      forControlEvents:UIControlEventTouchUpInside];
    [cell.contentView addSubview:playBtn];
}
else 
{
    mainLabel = (UILabel *)[cell.contentView viewWithTag:MAINLABEL_TAG];
    secondLabel = (UILabel *)[cell.contentView viewWithTag:SECONDLABEL_TAG];
    playBtn = (UIButton *)[cell.contentView viewWithTag:PLAYBTN_TAG];
}

// Alternate bg color
if (indexPath.row%2 == 0) {
    UIColor *altColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0
                                         blue:230.0/255.0 alpha:1];
    mainLabel.backgroundColor = altColor;
    secondLabel.backgroundColor = altColor;
}
else
{
    UIColor *altColor = [UIColor colorWithRed:255.0 green:255.0
                                         blue:255.0 alpha:1];
    mainLabel.backgroundColor = altColor;
    secondLabel.backgroundColor = altColor;
}

RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
NSLog(@"Entry: %@", entry);

// Manage play button
if (entry == currEntry)
{
    if(isPlaying)
    {
        [playBtn setBackgroundImage:pauseImage forState:UIControlStateNormal];
    }
    else
    {
        [playBtn  setBackgroundImage:playImage forState:UIControlStateNormal];
    }
}
else
    [playBtn setBackgroundImage:playImage forState:UIControlStateNormal];

mainLabel.text = entry.articleTitle;
secondLabel.text = entry.articleArtist;

return cell;
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.

DetailView *detailViewController = [[DetailView alloc] initWithNibName:@"DetailedView" bundle:[NSBundle mainBundle]];

RSSEntry *entry = [_allEntries objectAtIndex:[indexPath row]];



[self.navigationController pushViewController:detailViewController animated:YES];

detailViewController.songTitle.text = entry.articleTitle;
detailViewController.artistName.text = entry.articleArtist;

[entry release];

[detailViewController release];

}

- (void)dealloc
{
[player release];
player = nil;
[_queue release];
_queue = nil;
[_feed release];
_feed = nil;
[_allEntries release];
_allEntries = nil;

[super dealloc];
}

@end

【问题讨论】:

  • 不要在你的viewDidLoad: 中释放iVar,你应该在delloc 方法中这样做。删除这个:[self.feed release];。我不能确保它会解决你的问题。 :)
  • 所以当它在mainLabel.text = entry.articleTitle 上崩溃时,它实际上指向了一个错误的地址。我只是不知道我的 RSSEntry 对象是如何改变的。
  • 您确定错误地址是在entry 而不是mainLabel
  • 根据@Eiko 的回答,我发现您的pauseImageplayImage 是iVar!退出该方法后它们将被自动释放,只需遵循@Eiko 的建议即可。 ;)
  • @Kjuly 是的,我解决了这个问题。出于某种原因,我的articleTitlearticleArtist 在崩溃时为零。它们根本不应该改变。

标签: iphone objective-c ios uitableview memory-management


【解决方案1】:

如果没有行,你会崩溃很难说,但很可能你访问了一些被释放的对象

很可能在这里

self.feed = [[NSString alloc] initWithString:@"http://site.org/rss/music"];
[self.feed release];

您立即释放对象,但如果不知道您是否保留了财产,则很难判断

【讨论】:

  • 有时它会在“mainLabel.text = entry.articleTitle;”行崩溃
  • 很难看出 RSSEntry 会被释放,但当视图切换时我不会释放任何东西。反正我不这么认为……
  • 不是一个好的模式,但如果 feed 是一个“保留”属性,这里很可能没问题。 (我们不知道但应该期待)
【解决方案2】:

请不要释放任何@synthesize 变量。你应该只在 dealloc 方法中释放它

【讨论】:

  • 好电话,但我修好了它,它仍然是同样的情况。每当我离开 tableview 并回来时,它都会崩溃。
  • 我确定您发布了一些您不应该发布的变量。尝试对所有变量使用 NSAutoreleasePool。
【解决方案3】:

这是一个疯狂的猜测,但您不会保留在viewDidLoad 中获得的图像:

pauseImage = [UIImage imageNamed:@"pause_circle_small.png"];
playImage = [UIImage imageNamed:@"play_circle_small.png"];

要么使用保留属性和点语法,要么分别发送retain

【讨论】:

  • 啊,我没有在那里使用保留,所以是的,我解决了这个问题。不过还是崩溃了。
  • 如果它在 mainLabel.text = ... 行上崩溃,请在该行之前设置一个断点并检查标签和条目。
【解决方案4】:

请不要释放 self.feed 并且在卸载或解除分配视图时将委托 nil 表示为

tableview.delegate = nil;

这是在此之后检查的主要内容,我认为您不会取消 tableview 的代表。

【讨论】:

  • 你的意思是在 -dealloc 方法中我应该释放委托?不知道。但是直到程序结束才调用 dealloc。
【解决方案5】:

啊啊啊!!!在将 RSSEntry 放入 _allEntries 数组之前,我将它们设置为自动释放。当我改变观点时,他们正在被释放。不要那样做。感谢大家的帮助。太简单了,我现在感觉很傻。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多