ios - 关于cell重用的一些很纠结的问题(来大神解释下)
大家讲道理
大家讲道理 2017-04-17 16:54:14
0
5
612

static NSString *orderCellID = @"MyOrderCell";

[self.mTableView registerClass:[MyOrderCell class] forCellReuseIdentifier:orderCellID];
1.MyOrderCell *cell = (MyOrderCell *)[tableView dequeueReusableCellWithIdentifier:orderCellID];

    if (cell == nil) {

       cell = [[MyOrderCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:orderCellID];

    }
2.MyOrderCell *cell = [self.mTableView dequeueReusableCellWithIdentifier:orderCellID forIndexPath:indexPath];

这两种重用cell的方法问题就是...

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
    
    NSLog(@"cell height %f",cell.frame.size.height);
    
    return cell.frame.size.height;
}

如果用方法2.的话为什么
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
就报错了?????

但是用方法1的话确实是可行的...可以来个大神详细解释下吗

大家讲道理
大家讲道理

光阴似箭催人老,日月如移越少年。

reply all(5)
刘奇

Your two methods are actually the same, that is to say,

[self.mTableView dequeueReusableCellWithIdentifier:orderCellID forIndexPath:indexPath];

This method, regardless of whether there is a generated cell waiting for reuse, is guaranteed to return a cell (if there is one, it will be taken, if not, a new one will be generated). But there is a condition when calling this method, that is, you must have called the registerClass or registerNib method to register, which is written in this document.
The other method is to determine whether there are already generated cells waiting for reuse. If there are cells, take one and return it. If not, it will return nil. So you need to determine whether it is nil below and create it yourself.

[self tableView:tableView cellForRowAtIndexPath:indexPath];

This method cannot be called manually. The cells returned by this method are to be displayed on the interface and participate in reuse. If you call this method manually, the cells it returns will be useless and released after you calculate the height. When the calculation here in your code is high, a cell will be generated every time the method is called.

So the reuse issue you are struggling with is actually because you manually called the tableView:cellForRowAtIndexPath: function.

左手右手慢动作

1 Even if it is possible, the returned value should be nil

Peter_Zhu
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
    
    NSLog(@"cell height %f",cell.frame.size.height);
    
    return cell.frame.size.height;
}

This code usually cannot be written like this. To return the height, you cannot take the cell like this and then return the height. You must know that when this proxy method is called, - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath has not yet been executed. The calling order of the two must be understood.
Tableview needs to get the height in advance, and then returns the cell by reusing the cell. The cell is laid out according to the previous height.

So there are generally two ideas for proxy methods that return height:

  1. Get the height and spacing of various UI elements inside the cell and perform cumulative calculations. See the reference link below.

  2. If you use Autolayout constraints, use `[cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] to calculate the height. In this regard, you can refer to the open source project https://github.com/forkingdog/UITableView-FDTemplateLayoutCell

You can take a look at: Detailed explanation of dynamic calculation of UITableViewCell height

伊谢尔伦

The person above is right. It is best not to actively call the system's proxy method yourself, otherwise problems may arise if it is not fully guaranteed.
In addition, the original poster’s question: 2. MyOrderCell *cell = [self.mTableView dequeueReusableCellWithIdentifier:orderCellID forIndexPath:indexPath]; Why doesn’t it work like this?

Official documentation explains dequeueReusableCellWithIdentifier::
Returns a reusable table-view cell object located by its identifier.
A string identifying the cell object to be reused. This parameter must not be nil.

Returns A UITableViewCell object with the associated identifier or nil if no such object exists in the reusable-cell queue.

Did you see it? If you want to have a reusable cell, you must first create one! If you haven't created one yet, the system won't create one for you. The first method is correct, because when the system finds that there is no reusable cell, it returns nil, and then you alloc one yourself. This cell will be added to a queue by the system. Next time, you have to use the identifier The system will give you something when you reuse it
I found one for reference: link description

大家讲道理

The second method is that you need to register the cell in the tableView first

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template