2014-01-20 3 views
0

사용자 정의 클래스에서 빌드 된보기 목록이 포함 된 scrollview에서 작업 중입니다. 이 클래스는 이미지와 삭제 버튼 및 델리게이트가있는 뷰입니다. 삭제 버튼을 누르면 delegate 함수가 호출됩니다. 위임자는 scrollview이고 scrollview는 뷰에서 배열을 삭제합니다. 내가 가진 문제는 삭제 단추를 누를 때 항목이 배열에서 제거되지만 dealloc되지 않으므로 단추와 이미지가 화면에 남아있게된다는 것입니다.배열의 객체가 제거되었지만 dealloc되지 않았 음

처음으로 ARC를 사용하고 있는데 뭔가 잘못하고 있다고 느낍니다. 보통 나는 retain과 release를 사용하는 것이 좋을 것이고 이것을 디버깅 할 수는있을 것이지만 ARC는 나에게 신비감을 느낀다. 그리고 나는 왜 view가 dealloc을 얻지 못하게했는지 이해하지 못한다.

여기 내 코드입니다 :

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

배열 그냥보기에있는 버튼에 대한 참조를 유지하고있다. 배열에서 항목을 제거하면보기에서만 배열에서 항목을 제거하지 않습니다. 당신이 당신의 서브 뷰 자체에 추가되고 강한 포인터가 self.subviews에 추가됩니다

[self addSubview:yourSubview] 

를 호출 할 때

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

젠장, 좋은 캐치. 고마워요! – zaloo

2

:이 대신 같은이 필요합니다. 당신이의 dealloc 메소드가 호출됩니다있는 하위 뷰에 또 다른 강력한 포인터를 제거하면 당신이 서브 뷰를 제거 할 때 가장 먼저해야 할 일은 다음

[yourSubview removeFromSuperView] 

를 호출한다.

관련 문제