UITableView layout messing up on push segue and return. (iOS 8, Xcode beta 5, Swift)

后端 未结 7 883
清歌不尽
清歌不尽 2020-12-07 13:44

tldr; Auto constrains appear to break on push segue and return to view for custom cells

Edit: I have provided a github example proj

7条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-07 14:35

    The problem of this behavior is when you push a segue the tableView will call the estimatedHeightForRowAtIndexPath for the visible cells and reset the cell height to a default value. This happens after the viewWillDisappear call. If you come back to TableView all the visible cells are messed up..

    I solved this problem with a estimatedCellHeightCache. I simply add this code snipped to the cellForRowAtIndexPath method:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        ...
        // put estimated cell height in cache if needed
        if (![self isEstimatedRowHeightInCache:indexPath]) {
            CGSize cellSize = [cell systemLayoutSizeFittingSize:CGSizeMake(self.view.frame.size.width, 0) withHorizontalFittingPriority:1000.0 verticalFittingPriority:50.0];
            [self putEstimatedCellHeightToCache:indexPath height:cellSize.height];
        }
        ...
    }
    

    Now you have to implement the estimatedHeightForRowAtIndexPath as following:

    -(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
        return [self getEstimatedCellHeightFromCache:indexPath defaultHeight:41.5];
    }
    

    Configure the Cache

    Add this property to your .h file:

    @property NSMutableDictionary *estimatedRowHeightCache;
    

    Implement methods to put/get/reset.. the cache:

    #pragma mark - estimated height cache methods
    
    // put height to cache
    - (void) putEstimatedCellHeightToCache:(NSIndexPath *) indexPath height:(CGFloat) height {
        [self initEstimatedRowHeightCacheIfNeeded];
        [self.estimatedRowHeightCache setValue:[[NSNumber alloc] initWithFloat:height] forKey:[NSString stringWithFormat:@"%d", indexPath.row]];
    }
    
    // get height from cache
    - (CGFloat) getEstimatedCellHeightFromCache:(NSIndexPath *) indexPath defaultHeight:(CGFloat) defaultHeight {
        [self initEstimatedRowHeightCacheIfNeeded];
        NSNumber *estimatedHeight = [self.estimatedRowHeightCache valueForKey:[NSString stringWithFormat:@"%d", indexPath.row]];
        if (estimatedHeight != nil) {
            //NSLog(@"cached: %f", [estimatedHeight floatValue]);
            return [estimatedHeight floatValue];
        }
        //NSLog(@"not cached: %f", defaultHeight);
        return defaultHeight;
    }
    
    // check if height is on cache
    - (BOOL) isEstimatedRowHeightInCache:(NSIndexPath *) indexPath {
        if ([self getEstimatedCellHeightFromCache:indexPath defaultHeight:0] > 0) {
            return YES;
        }
        return NO;
    }
    
    // init cache
    -(void) initEstimatedRowHeightCacheIfNeeded {
        if (self.estimatedRowHeightCache == nil) {
            self.estimatedRowHeightCache = [[NSMutableDictionary alloc] init];
        }
    }
    
    // custom [self.tableView reloadData]
    -(void) tableViewReloadData {
        // clear cache on reload
        self.estimatedRowHeightCache = [[NSMutableDictionary alloc] init];
        [self.tableView reloadData];
    }
    

提交回复
热议问题