重新加载时不会释放UITableViewCell

时间:2013-11-17 19:22:40

标签: objective-c uitableview automatic-ref-counting

迁移到ARC后优化我的代码我遇到了以下问题:

我有一个UITableView,其中有两个单元格:DOArticleHeaderCellDOArticleContentCell。 内容单元格有DOWebView,它是UIWebview,具有在加载时执行回调的功能,因此可以重新加载单元格并调整高度。

DOWebView.h:

@interface DOWebView : UIWebView <UIWebViewDelegate> {
    bool _reload;
    __weak id <DOWebViewCallback> _callback;
}

@property (weak, nonatomic) id <DOWebViewCallback> callback;

- (void) loadHTMLString:(NSString*) text baseURL:(NSURL*) url;
- (void) updateWebview;
- (void) stopWebview;

@end

DOWebView.m

- (void)webViewDidFinishLoad:(UIWebView *)aWebView
{
    if([super respondsToSelector:@selector(scrollView)]) {
        super.scrollView.scrollEnabled = false;
    }

    id appDelegate = (iDomsAppDelegate *)[[UIApplication sharedApplication] delegate];

    // finished loading, hide the activity indicator in the status bar
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    DOSetting *zoomLevel = (DOSetting *)[[appDelegate dataManager] findSetting:@"zoomLevel"];

    [super stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"document.getElementsByTagName('body')[0].style.webkitTextSizeAdjust= '%@%%'", zoomLevel.value]];

    if(![zoomLevel.value isEqualToString:@"100"]){
        // Allows the web view to update itself with new scroll 
        [self performSelector:@selector(correctSize) withObject:nil afterDelay:1];
    } else {
        [self correctSize];
    }

}

- (void) correctSize {
    CGSize fittingSize = [super sizeThatFits:CGSizeZero];
    if((fittingSize.height > [super frame].size.height) || ([super frame].size.height - fittingSize.height > 50)){
        if([super delegate] == nil) {
            return;
        }
        [self stopWebview];
        if(_reload || fittingSize.height - [super frame].size.height > 50){
            [_callback setContentSizeAndReloadData:fittingSize.height reloadAnyway:true];
        } else {
            [_callback setContentSizeAndReloadData:fittingSize.height reloadAnyway:false];
        }
    }
    _reload = false;
}

这要求以下内容:

@interface DOArticleContentCell : DOPrototypeCell <DOWebViewCallback> {
    @private
    __weak IBOutlet DOWebView* _webView;
    __weak IBOutlet UIButton* _websiteBttn;
    __weak IBOutlet UIButton* _shareBttn;
    __weak IBOutlet UIButton* _fullscreenBttn;

    __weak IBOutlet UIButton* _increaseFontSizeBttn;
    __weak IBOutlet UIButton* _decreateFontSizeBttn;
    __weak IBOutlet UIButton* _resetFontSizeBttn;

    //bool _reload;
    __weak DOArticle* _article;
    //__weak DOSocialMediaHelper* _socialMediaHelper;
}

@property (nonatomic, weak) DOArticle *article;
@property (nonatomic, weak) DOWebView* webView;
@property (weak, nonatomic) id <DOArticleViewControllerDelegate> delegate;

- (IBAction)showActionSheet:(id)sender;
- (IBAction)increaseFontSize:(id)sender;
- (IBAction)decreaseFontSize:(id)sender;
- (IBAction)openWebsite:(id)sender;
- (void) populateCellSimple:(NSString *) htmlText;

@end

使用回调函数调用tableView:

- (void) setContentSizeAndReloadData:(int)size reloadAnyway:(bool)reload {
    //__weak DOArticleContentCell *weakLink = self;

    __weak id weakSelf = self;
    [delegate setContentSizeAndReloadData:weakSelf size:size reloadAnyway:reload];
}

DOArticleViewController.h:

@interface DOArticleViewController : DOPrototypeViewController <DOArticleViewControllerDelegate> {
    DOArticle* _article; 
    int _fittingSize;
    bool _didReloadContentRow;
    bool _notification;  
    bool _multiLanguages;

    __weak IBOutlet UITableView * _tableView;
    IBOutlet DOAudioControllerCell* _audioCell;    
}

- (IBAction)fullScreen:(id)sender;
- (void) reloadArticle:(DOArticle*) article;
- (void) unLoad;

@property (nonatomic, strong) DOArticle *article;
@property (nonatomic) bool *notification;
@property (nonatomic, weak) UITableView *tableView;


@end

在DOArticleViewController.m中:

#pragma mark - Delegate
- (void) setContentSizeAndReloadData:(DOArticleContentCell *) cell size:(int) size reloadAnyway:(bool)reload {

    _fittingSize = size;

    // For now only do when not set. Otherwise there is an issue with a wider frame, as there would be a lot of white under it and no known way at present to detect this without creating a smaller fraome first and to reload.
    if([_article.estimatedHeight intValue] <= 0){
       // NSLog(@"Updating article height and saved! (%i vs %i)", [_article.estimatedHeight intValue], size);
        _article.estimatedHeight = [NSNumber numberWithInt:size];

        id appDelegate = (iDomsAppDelegate *)[[UIApplication sharedApplication] delegate];
        [[appDelegate dataManager] commitChanges];
    }

    if(!_didReloadContentRow || reload){
        NSIndexPath *indexPath = [_tableView indexPathForCell:cell];

        // Remove the delagate incase it relaods
        [[cell webView] stopWebview];

        [_tableView beginUpdates];
        [_tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [_tableView endUpdates];

    }

    _didReloadContentRow = true;
}

如果我将[_tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];取出,则释放可以正常运行,但如果在父版本发布后DOArticleHeaderCellDOArticleContentCell处于活动状态,则该版本仍然有效。

1 个答案:

答案 0 :(得分:0)

我认为这个特定问题可能是由于使用了模拟器,因为在设备上运行相同的测试时它不会出现。我不是100%肯定,但似乎就是这样。