2011-05-29 60 views
2

我一直在调试过去几个小时的以下问题,似乎无法得出一个好的结论。消息发送到释放实例问题

- [NSIndexPath行]:发送到0x506cf90

我在执行上的UITableView的每一个小区的识别器​​滑动释放实例消息。每当检测到滑动,下面的代码将被调用。它所做的是显示/隐藏单元格中的子视图。如果子视图已经显示,则隐藏,否则显示。如果一个子视图已经显示在单元格5上,并且在单元格3上检测到刷卡,那么我们先删除该子视图,然后在单元格3上添加子视图。

我试过下面的代码,它似乎适用于某些单元格。但是,特别是在UITableView底部有一个单元格,如果我试图隐藏子视图,它会给我上面的错误。它对于其他单元格来说工作得很好,只是单元格在底部。为什么是这样?

的代码如下:

- (void)swipe:(UISwipeGestureRecognizer *)recognizer direction:(UISwipeGestureRecognizerDirection)direction 
{ 
    if (recognizer && recognizer.state == UIGestureRecognizerStateEnded) 
    { 
     // Get the table view cell where the swipe occured 
     CGPoint location = [recognizer locationInView:self.table]; 
     NSIndexPath* indexPath = [self.table indexPathForRowAtPoint:location]; 
     ConvoreCell* cell = (ConvoreCell *) [self.table cellForRowAtIndexPath:indexPath]; 

     [self.table beginUpdates]; 

     NSLog(@"ROW is %d", global.row); 
     //removing the options view at the other cell before adding a new one 
     if (global != nil && global.row != indexPath.row){ 
      [sideSwipeView removeFromSuperview]; 
      [sideSwipeView release]; 
      sideSwipeView = nil; 
     } 

     //options already exist, we need to remove it 
     if (sideSwipeView != nil){ 
      [sideSwipeView removeFromSuperview]; 
      [sideSwipeView release]; 
      sideSwipeView = nil; 
      slide = NO; 
     } else { 
      //options do not exist and therefore we need to add it 
      NSArray * buttonData = [[NSArray arrayWithObjects: 
            [NSDictionary dictionaryWithObjectsAndKeys:@"Mark Read", @"title", @"mark.png", @"image", nil], 
            [NSDictionary dictionaryWithObjectsAndKeys:@"Track", @"title", @"play.png", @"image", nil], 
            [NSDictionary dictionaryWithObjectsAndKeys:@"Leave", @"title", @"delete.png", @"image", nil], 
            nil] retain]; 

      NSMutableArray * buttons = [[NSMutableArray alloc] initWithCapacity:buttonData.count]; 
      sideSwipeView = [[UIView alloc] initWithFrame:CGRectMake(0, cell.frame.size.height-25, 320, 25)]; 
      [sideSwipeView setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin]; 
      [sideSwipeView setBackgroundColor:[UIColor colorWithPatternImage: [UIImage imageNamed:@"dotted-pattern.png"]]]; 
      [sideSwipeView setTag:-10]; 

      CGFloat leftEdge = BUTTON_LEFT_MARGIN; 
      for (NSDictionary* buttonInfo in buttonData) 
      { 
       if (!([[buttonInfo objectForKey:@"title"] isEqualToString:@"Mark Read"] && [[[groups objectAtIndex:indexPath.row] unread] intValue] == 0)) 
       { 

        UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom]; 

        button.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin; 

        UIImage* buttonImage = [UIImage imageNamed:[buttonInfo objectForKey:@"image"]]; 
        if ([[[groups objectAtIndex:indexPath.row] tracked] intValue] == 1 && [[buttonInfo objectForKey:@"title"] isEqualToString:@"Track"]){ 
         buttonImage = [UIImage imageNamed:@"pause.png"]; 
         [button setSelected:YES]; 
        } else 
         [button setSelected:NO]; 

        button.frame = CGRectMake(leftEdge, 0, buttonImage.size.width, buttonImage.size.height); 

        UIImage* grayImage = [self imageFilledWith:[UIColor colorWithWhite:0.9 alpha:1.0] using:buttonImage]; 
        [button setImage:grayImage forState:UIControlStateNormal]; 

        if ([[buttonInfo objectForKey:@"title"] isEqualToString:@"Mark Read"]){ 
         [button addTarget:self action:@selector(markRead:) forControlEvents:UIControlEventTouchUpInside]; 
        } else if ([[buttonInfo objectForKey:@"title"] isEqualToString:@"Track"]){ 
         [button addTarget:self action:@selector(track:) forControlEvents:UIControlEventTouchUpInside]; 
        } else if ([[buttonInfo objectForKey:@"title"] isEqualToString:@"Leave"]){ 
         [button addTarget:self action:@selector(leave:) forControlEvents:UIControlEventTouchUpInside]; 
        } 
        [button setTag:indexPath.row]; 
        [buttons addObject:button]; 

        [sideSwipeView addSubview:button]; 
        leftEdge = leftEdge + buttonImage.size.width + BUTTON_SPACING; 
       } 
      } 

      [cell.contentView addSubview:sideSwipeView]; 
      [buttons release]; 
      [buttonData release]; 
      global = indexPath; 
      slide = YES; 

     } 
     [self.table endUpdates]; 
     [self.table deselectRowAtIndexPath:indexPath animated:YES];   

    } 
} 

现在,这里的问题是,指针indexPath不知何故释放。我能够通过制作indexPath的副本而不是仅仅引用指针来解决这个问题。所以我做:

global = [indexPath copy]; 

由于某种原因,这种方法被称为它会释放indexPath,我不知道谁做之后..我认为iOS的做这......是真的吗?

回答

2
NSIndexPath* indexPath = [self.table indexPathForRowAtPoint:location]; 

返回一个自动释放实例。所以,是的,你的任务分配到global需要保留这个对象。 copy有效返回保留的实例。

不要泄漏,但。如果你只是做:

global = [indexPath copy]; 

你不释放global第一原始值,你会泄漏。

哦,还有:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

+0

indexPathForRowAtPoint:不一定返回一个自动释放的情况下(我不确定它是否真的如此)。它返回一个无主的实例。这种错误在某些情况下会带来乐趣。 objectAtIndex:then removeObjectAtIndex:例如。 2011-05-29 05:30:58

+0

所以在我做副本之前我需要做全球发布吗? – adit 2011-05-29 05:54:57

+0

是安全的,是的。否则以前在全球任何时候会泄漏 – 2011-05-29 06:10:48

相关问题