首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用rightView重新加载包含UITextField的行会导致无限循环和内存溢出

使用rightView重新加载包含UITextField的行会导致无限循环和内存溢出
EN

Stack Overflow用户
提问于 2016-08-08 18:15:49
回答 1查看 298关注 0票数 1

我遇到了一个奇怪的bug,那就是用自定义的rightView重新加载包含UITableViewCellUITextField

我创建了一个非常简单的示例来演示这个bug:

具有UITextField的自定义单元格

代码语言:javascript
复制
@implementation TableViewCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        _textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
        _textField.text = @"This is a text field";
        [self.contentView addSubview:_textField];
    }

    return self;
}

@end

我的带有UITableView的视图控制器

代码语言:javascript
复制
@interface ViewController () <UITableViewDataSource>

@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (nonatomic) UIView *rightView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // Press to reload the row with rightView
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(reloadRow)];

    // Create rightView and store to a property
    _rightView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 24, 24)];
    _rightView.backgroundColor = [UIColor greenColor];

    [_tableView registerClass:[TableViewCell class] forCellReuseIdentifier:@"Cell"];
    _tableView.dataSource = self;
}

- (void)reloadRow {
    [_tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0
                                                            inSection:0]]
                      withRowAnimation:(UITableViewRowAnimationAutomatic)];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    cell.textField.rightView = _rightView;
    cell.textField.rightViewMode = UITextFieldViewModeAlways;

    return cell;
}

@end

就这样。然后我按下重新加载按钮。无限循环开始,应用程序挂起。几秒钟后,应用程序崩溃,因为它使用了太多的内存:

Terminated due to memory error.

但是,如果我不将rightView存储在属性中,并在每次tableView将单元出队时创建新视图,那么就不会有问题。

代码语言:javascript
复制
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    cell.textField.rightView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 24, 24)];
    cell.textField.rightView.backgroundColor = [UIColor greenColor];
    cell.textField.rightViewMode = UITextFieldViewModeAlways;

    return cell;
}

但是我的rightView (在真实的应用程序中)不是一个简单的视图,所以我不想在每次出现行时都重新创建它。

有人知道为什么会这样吗?如果我不存储rightView,为什么它没有发生?感谢您的阅读。

EN

回答 1

Stack Overflow用户

发布于 2016-08-08 18:31:00

您尝试将一个视图添加到多个superview。你不能这么做。您的@property (nonatomic) UIView *rightView只能有一个superView。尝试将其从子视图cell.textField.subviews中删除

代码语言:javascript
复制
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    for (UIView *subview in cell.textField.subviews) {
        if ([subview isEqual:_rightView]) {
           [subview removeFromSuperView];
        }
    }
    cell.textField.rightView = _rightView;
    cell.textField.rightViewMode = UITextFieldViewModeAlways;

    return cell;
}

或者创建一个将返回rightView实例的fabric方法

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38826608

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档