数组中的对象已删除,但未被删除

时间:2014-01-20 17:05:52

标签: ios objective-c nsarray automatic-ref-counting

我正在处理一个包含从自定义类构建的视图列表的scrollview。此类是具有图像和删除按钮以及委托的视图。当我按下删除按钮时,它调用委托函数(委托是scrollview,scrollview从数组中删除视图以删除它)。我遇到的问题是,当按下删除按钮时,该项目将被删除,但不会被删除,因此按钮和图像将保留在屏幕上。

我第一次使用ARC而且我有一种感觉我做错了什么。通常我可以使用保留和释放,我可以调试这个,但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

2 个答案:

答案 0 :(得分:3)

您的按钮数组只是保持对视图上按钮的引用。通过从数组中删除项目,您无法从数组中将其从视图中删除。你需要有这样的东西:

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

答案 1 :(得分:2)

致电时

[self addSubview:yourSubview]

你的子视图被添加到self中,并且一个强指针被添加到self.subviews。当你想删除subView时,你需要做的第一件事就是调用

[yourSubview removeFromSuperView]

然后,如果您还删除了任何其他指向子视图的强指针,那么将调用dealloc方法。