2014-01-20 74 views
0

我正在處理包含從自定義類構建的視圖列表的scrollview。這個類是具有圖像和刪除按鈕和委託的視圖。當我按下刪除按鈕時,它調用委託函數(委託是滾動視圖,滾動視圖從數組中刪除視圖以刪除它)。我遇到的問題是,當按下刪除按鈕時,該項目在陣列上被刪除,但未被解除分配,因此按鈕和圖像仍保留在屏幕上。已刪除數組中的對象,但未解除分配

我第一次使用ARC,我感覺我做錯了什麼。通常我可以使用retain和release,但我可以調試,但ARC對我來說感覺很神祕,而且我爲什麼沒有獲得dealloc'd的視圖,我有點難住。

這裏是我的代碼:

VideoScrollView:

#import <UIKit/UIKit.h> 
#import "VideoButtonView.h" 

@interface VideoScrollView: UIScrollView <VideoButtonViewDelegate> 

@property (retain, nonatomic)   NSMutableArray *buttonArray; 

- (void)setScrollViewContentSize: (CGSize) minimumSize; 
- (void)buttonAdded: (UIImage*)image withMinimumSize: (CGSize) minimumSize; 
- (void)respondToDelete:(id)sender; 

@end 


#import "VideoScrollView.h" 

@implementation VideoScrollView 


#define BUTTON_SIDE_LENGTH 60 
#define BUTTON_BUFFER_LENGTH 10 
#define INSET_HEIGHT 0 
#define INSET_WIDTH 0 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code 
     self.buttonArray = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     // Initialization code 
     self.buttonArray = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

- (id)initWithCoder:(NSCoder *)decoder { 
    self = [super initWithCoder:decoder]; 
    if (self) { 
     self.buttonArray = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 


-(BOOL)touchesShouldCancelInContentView:(UIView *)view { 
    if([view class] == [UIButton class]) 
     return true; 
    return [super touchesShouldCancelInContentView:view]; 
} 

- (void)setScrollViewContentSize: (CGSize) minimumSize { 
    float scrollViewWidth = self.frame.size.width; 
    float buttons_per_row = scrollViewWidth/(BUTTON_SIDE_LENGTH + BUTTON_BUFFER_LENGTH); 
    float num_rows = ceil([self.buttonArray count]/floorf(buttons_per_row)); 

    self.contentInset = UIEdgeInsetsMake(INSET_HEIGHT, INSET_WIDTH, INSET_HEIGHT, INSET_WIDTH); 

    CGFloat min_width = minimumSize.height - INSET_HEIGHT*2; 
    CGFloat acutal_width = (BUTTON_SIDE_LENGTH + BUTTON_BUFFER_LENGTH) * num_rows + BUTTON_BUFFER_LENGTH; 
    CGFloat contentHeight = MAX(acutal_width, min_width); 
    CGSize temp_size = CGSizeMake(minimumSize.width, contentHeight); 
    self.contentSize = temp_size; 
} 

- (void)setButtonLocations { 
    float scrollViewWidth = self.frame.size.width; 
    float buttons_per_row = scrollViewWidth/(BUTTON_SIDE_LENGTH + BUTTON_BUFFER_LENGTH); 
    //float num_rows = 0; 
    //num_rows = ceil([self.buttonArray count]/floorf(buttons_per_row)); 

    float offset = scrollViewWidth - (BUTTON_SIDE_LENGTH + BUTTON_BUFFER_LENGTH)*buttons_per_row + BUTTON_BUFFER_LENGTH; 
    offset/=2; 

    int count = 0; 
    for(UIButton *button in self.buttonArray) { 
     CGFloat button_x = (CGFloat)(count % (int)buttons_per_row)*(BUTTON_SIDE_LENGTH + BUTTON_BUFFER_LENGTH) + BUTTON_BUFFER_LENGTH + offset; 
     CGFloat button_y = (CGFloat)floorf(count/(int)buttons_per_row)*(BUTTON_SIDE_LENGTH + BUTTON_BUFFER_LENGTH) + BUTTON_BUFFER_LENGTH; 

     button.frame = CGRectMake(button_x, button_y, BUTTON_SIDE_LENGTH, BUTTON_SIDE_LENGTH); 

     count++; 
    } 
} 

- (void)buttonAdded: (UIImage*)image withMinimumSize: (CGSize) minimumSize { 
    int scrollViewWidth = self.frame.size.width; 
    int buttons_per_row = scrollViewWidth/(BUTTON_SIDE_LENGTH + BUTTON_BUFFER_LENGTH); 

    int button_count = [self.buttonArray count]; 
    CGFloat button_x = (CGFloat)(button_count % buttons_per_row)*(BUTTON_SIDE_LENGTH + BUTTON_BUFFER_LENGTH) + BUTTON_BUFFER_LENGTH; 
    CGFloat button_y = (CGFloat)floor(button_count/buttons_per_row)*(BUTTON_SIDE_LENGTH + BUTTON_BUFFER_LENGTH) + BUTTON_BUFFER_LENGTH; 

    VideoButtonView* temp_button_view = [[VideoButtonView alloc] initWithFrame:CGRectMake(button_x, button_y, BUTTON_SIDE_LENGTH, BUTTON_SIDE_LENGTH)]; 
    temp_button_view.delegate = self; 

    [self addSubview:temp_button_view]; 

    [self.buttonArray addObject:temp_button_view]; 

    [self setScrollViewContentSize:minimumSize]; 
} 

- (void)respondToDelete: (id)sender 
{ 
    [self.buttonArray removeObject:sender]; 

} 

@end 

VideoButtonView:

#import <UIKit/UIKit.h> 

@protocol VideoButtonViewDelegate <NSObject> 

- (void)respondToDelete: (id)sender; 

@end 

@interface VideoButtonView : UIView 


@property (retain, nonatomic) UIButton *videoButton; 
@property (retain, nonatomic) UIButton *deleteButton; 

@property(nonatomic,assign)id<VideoButtonViewDelegate> delegate; 

@end 

#import "VideoButtonView.h" 

#define DELETE_BUTTON_LENGTH 5 

@implementation VideoButtonView 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     self.videoButton = [[UIButton alloc] init]; 
     [self.videoButton setBackgroundColor:[UIColor blueColor]]; 

     self.deleteButton = [[UIButton alloc] init]; 

     [self setFrame:frame]; 

     [self.deleteButton addTarget:self action:@selector(deletePressed:) forControlEvents:UIControlEventTouchUpInside]; 

     [self.deleteButton setBackgroundImage:[[UIImage imageNamed:@"delete_button.png"] 
               stretchableImageWithLeftCapWidth:8.0f 
               topCapHeight:0.0f] 
              forState:UIControlStateNormal]; 

     [self.deleteButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 
     [self.deleteButton setTitle:@"Delete" forState:UIControlStateNormal]; 
     self.deleteButton.titleLabel.font = [UIFont boldSystemFontOfSize:6]; 
     self.deleteButton.titleLabel.shadowColor = [UIColor lightGrayColor]; 
     self.deleteButton.titleLabel.shadowOffset = CGSizeMake(0, -1); 

     [self addSubview:self.videoButton]; 
     [self addSubview:self.deleteButton]; 

     [self bringSubviewToFront:self.deleteButton]; 

    } 
    return self; 
} 

-(void)deletePressed: (id)sender { 
    if([self.delegate respondsToSelector:@selector(respondToDelete:)]) 
    { 
     //send the delegate function with the amount entered by the user 
     [self.delegate respondToDelete:self]; 
    } 

} 

-(void) setFrame:(CGRect)frame 
{ 
    [super setFrame:frame]; 

    CGRect video_frame = CGRectMake(0, 0, frame.size.width, frame.size.height); 
    [self.videoButton setFrame:video_frame]; 
    [self.videoButton setBackgroundColor:[UIColor blueColor]]; 

    CGFloat delete_y = frame.size.height - 15; 
    CGRect deleteFrame = CGRectMake(10, delete_y, 40, 10); 
    [self.deleteButton setFrame:deleteFrame]; 
} 



/* 
// Only override drawRect: if you perform custom drawing. 
// An empty implementation adversely affects performance during animation. 
- (void)drawRect:(CGRect)rect 
{ 
    // Drawing code 
} 
*/ 

@end 

回答

3

你的按鈕數組只是保持引用到是在視圖上的按鈕。通過從數組中刪除一個項目,您不會從視圖中刪除它,只需從數組中刪除它。你需要有這樣的事情,而不是:

- (void)respondToDelete: (id)sender { 
    [sender removeFromSuperview]; 
    [self.buttonArray removeObject:sender]; 
} 
+0

該死的,趕上。謝啦! – zaloo

2

當你調用

[self addSubview:yourSubview] 

你的子視圖加入到自我和強大的指針被添加到self.subviews。你需要的時候,你要刪除的子視圖要做的第一件事就是打電話

[yourSubview removeFromSuperView] 

如果您還刪除任何其他強大的指針,你有dealloc方法將被稱爲子視圖。