Don_Mag

Cell Resize Example

Oct 15th, 2021
788
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // resizing table view cells on data change
  2.  
  3. import UIKit
  4.  
  5. struct MyDataStruct {
  6.     var title: String = ""
  7.     var tapCount: Int = 0
  8. }
  9.  
  10. class SimpleCell: UITableViewCell {
  11.    
  12.     var callback: ((Int, UITableViewCell)->())?
  13.    
  14.     let theLabel: UILabel = {
  15.         let v = UILabel()
  16.         v.numberOfLines = 0
  17.         v.backgroundColor = .yellow
  18.         return v
  19.     }()
  20.    
  21.     let btn: UIButton = {
  22.         let v = UIButton()
  23.         v.backgroundColor = .systemRed
  24.         return v
  25.     }()
  26.    
  27.     private var title: String = ""
  28.     private var tapCount: Int = 0
  29.    
  30.     override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  31.         super.init(style: style, reuseIdentifier: reuseIdentifier)
  32.         commonInit()
  33.     }
  34.     required init?(coder: NSCoder) {
  35.         super.init(coder: coder)
  36.         commonInit()
  37.     }
  38.     func setData(_ d: MyDataStruct) -> Void {
  39.         title = d.title
  40.         tapCount = d.tapCount
  41.         theLabel.text = title + " Taps: \(tapCount)"
  42.     }
  43.     func commonInit() -> Void {
  44.         [theLabel, btn].forEach { v in
  45.             v.translatesAutoresizingMaskIntoConstraints = false
  46.             contentView.addSubview(v)
  47.         }
  48.         let g = contentView.layoutMarginsGuide
  49.        
  50.         NSLayoutConstraint.activate([
  51.            
  52.             theLabel.topAnchor.constraint(equalTo: g.topAnchor),
  53.             theLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor),
  54.             theLabel.bottomAnchor.constraint(lessThanOrEqualTo: g.bottomAnchor),
  55.            
  56.             btn.topAnchor.constraint(equalTo: g.topAnchor),
  57.             btn.trailingAnchor.constraint(equalTo: g.trailingAnchor),
  58.             btn.bottomAnchor.constraint(lessThanOrEqualTo: g.bottomAnchor),
  59.             btn.widthAnchor.constraint(equalToConstant: 100.0),
  60.            
  61.             btn.leadingAnchor.constraint(equalTo: theLabel.trailingAnchor, constant: 8.0),
  62.         ])
  63.        
  64.         btn.setTitle("Tap Me", for: [])
  65.         btn.addTarget(self, action: #selector(gotTap(_:)), for: .touchUpInside)
  66.     }
  67.    
  68.     @objc func gotTap(_ sender: Any) {
  69.         tapCount += 1
  70.         theLabel.text = title + " Taps: \(tapCount)"
  71.         callback?(tapCount, self)
  72.     }
  73.    
  74. }
  75.  
  76. class RowSizingTableViewController: UITableViewController {
  77.  
  78.     var myData: [MyDataStruct] = []
  79.    
  80.     override func viewDidLoad() {
  81.         super.viewDidLoad()
  82.        
  83.         for i in 0..<20 {
  84.             let t = MyDataStruct(title: "Row: \(i)", tapCount: 0)
  85.             myData.append(t)
  86.         }
  87.        
  88.         tableView.register(SimpleCell.self, forCellReuseIdentifier: "cell")
  89.     }
  90.  
  91.     // MARK: - Table view data source
  92.  
  93.     override func numberOfSections(in tableView: UITableView) -> Int {
  94.         return 1
  95.     }
  96.  
  97.     override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  98.         return myData.count
  99.     }
  100.  
  101.     override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
  102.         print(#function, indexPath, myData[indexPath.row])
  103.         return CGFloat(60 + (myData[indexPath.row].tapCount * 20))
  104.     }
  105.  
  106.     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  107.         let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! SimpleCell
  108.  
  109.         cell.setData(myData[indexPath.row])
  110.  
  111.         cell.callback = { [weak self] n, c in
  112.             guard let self = self,
  113.                   let pth = self.tableView.indexPath(for: c)
  114.             else { return }
  115.  
  116.             // update data
  117.             self.myData[pth.row].tapCount = n
  118.            
  119.             // both
  120.             //  beginUpdates() / endUpdates()
  121.             // and
  122.             //  performBatchUpdates()
  123.             // seem to work fine...
  124.            
  125.             self.tableView.beginUpdates()
  126.             self.tableView.endUpdates()
  127.            
  128.             //self.tableView.performBatchUpdates(nil, completion: nil)
  129.            
  130.         }
  131.        
  132.         return cell
  133.     }
  134.  
  135. }
  136.  
RAW Paste Data