9 Replies
      Latest reply on Jul 22, 2019 4:34 AM by Import EV Corporation
      Import EV Corporation Level 1 Level 1 (0 points)

        I created a tableview using custom cell. I want reload the target cell, let's say [section = 0, row = 0], and use the UITableView.reloadRows method.

        let indexPath = IndexPath.init(row: 0, section: 0)
        self.tableView.reloadRows(at: [indexPath], with: .fade)

        When the button in the target cell is tapped, this method is called.

         

        When this method called, the target cell [section = 0, row = 0] is not reloaded, but the tableview is scrolled and other cells [(section = 0, row = 2),(section = 0, row = 3)] are reloaded.

         

        I have no idea why this happens.

        Please help me if anyone has any solutions.

        Best regards,

        • Re: UITableView.reloadRows does not reload the target row.
          Import EV Corporation Level 1 Level 1 (0 points)

          Additional info;

          I use big cell size.

          Height of the cell is bigger than height of the screen.

          If I use relatively small cell, it works fine.

          But, if I use bigger cells, it does not work correctly.

           

          I use a big photo image in each cell and some of them are as big as screen size.

           

          Is this normal behavier of this method?

            • Re: UITableView.reloadRows does not reload the target row.
              Import EV Corporation Level 1 Level 1 (0 points)

              To Apple Technical Support personel,

               

              Please try the following code to find the problem I have been facing.

               

              import UIKit
              
              class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
                  
                  @IBOutlet weak var aTableView: UITableView!
                   var isTapped: Bool = false
              
                  override func viewDidLoad() {
                      super.viewDidLoad()
                      aTableView.delegate = self
                      aTableView.dataSource = self
                  }
                  
                  func numberOfSections(in tableView: UITableView) -> Int {
                      return 1
                  }
                  
                  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                      return 50
                  }
                  
                  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
                      if indexPath.row == 0 {
                          return 100.0
                      }
                      return 50.0
                  }
                  
                  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                      print("cellForRowAt:", indexPath)
                      let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
                      cell.textLabel!.text = "cell \(indexPath.row)"
                      if isTapped {
                          cell.backgroundColor = .red
                          isTapped = false
                      }
                      return cell
                  }
                  
                  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
                      print("didSelectRowAt:", indexPath)
                      isTapped = true
                      tableView.reloadRows(at: [indexPath], with: .none)
                  }
              }

               

              Launch the app and scroll the tableView by 50 point, which is half height of cell 0, then tap cell 0. If you use iPhone8,7,6, the background of cell 14 becomes red instead of cell 0.

              You can also find the print "didSelectRowAt: [0, 0]" and "cellForRowAt: [0, 14]".

               

              Is this an UITableView's bug, or correct behavier?

              Please try it and give me your comment.

               

              Best regards,

            • Re: UITableView.reloadRows does not reload the target row.
              Claude31 Level 8 Level 8 (6,385 points)

              Whet happens if you set animation to .none ?

                • Re: UITableView.reloadRows does not reload the target row.
                  Import EV Corporation Level 1 Level 1 (0 points)

                  Same.

                  It does not matter if you set animation to .none or any other option.

                    • Re: UITableView.reloadRows does not reload the target row.
                      Import EV Corporation Level 1 Level 1 (0 points)

                      You can reproduce the same symptom by the following code;

                      func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
                              if indexPath.row == 0 {
                                  return 100.0
                              }
                              return 50.0
                          }
                      

                      When you create this tableView and scroll up by around 50 point, then tap cell 0.

                      Please try it.

                        • Re: UITableView.reloadRows does not reload the target row.
                          Claude31 Level 8 Level 8 (6,385 points)

                          I tried and got the problem.

                           

                          - when you reload, you reload only thells that were not visible (the 1'th for instance), not the first.

                          I changed the code to set a red background for each cell ; it will be displayed when selected.

                           

                          import UIKit
                          
                          class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
                             
                              @IBOutlet weak var aTableView: UITableView!
                              var isTapped: Bool = false
                             
                              override func viewDidLoad() {
                                  super.viewDidLoad()
                                  aTableView.delegate = self
                                  aTableView.dataSource = self
                              }
                             
                              func numberOfSections(in tableView: UITableView) -> Int {
                                  return 1
                              }
                             
                              func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                                  return 50
                              }
                             
                              func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
                                  if indexPath.row == 0 {
                                      return 100.0
                                  }
                                  return 50.0
                              }
                             
                              func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                          //        print("cellForRowAt:", indexPath)
                                  let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
                                  cell.textLabel!.text = "cell \(indexPath.row)"
                          //        if isTapped {
                          //            cell.backgroundColor = .red
                                      isTapped = false
                          //        }
                                  let backgroundView = UIView()
                                  backgroundView.backgroundColor = .red
                                  cell.selectedBackgroundView = backgroundView
                          
                                  return cell
                              }
                             
                              func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
                                  print("didSelectRowAt:", indexPath)
                                  isTapped = true
                          //        tableView.reloadRows(at: [indexPath], with: .none)
                              }
                          
                          
                          }
                            • Re: UITableView.reloadRows does not reload the target row.
                              Import EV Corporation Level 1 Level 1 (0 points)

                              Thank you for you response.

                               

                              It seems working in case of background color.

                               

                              This code is just a sample code to let everyone know the problem ("reloadRows" does not work correctly).

                              You mentioned that reload is just applied to the cells that are not visible.

                              Is this true?

                              I thought reload is applied to all cells.

                              Am I wrong?

                               

                              Anyway,

                              What I would like to do is to change selected cell height.

                               

                              I am developing news feed app and using a tableView to display each news in each cell.

                              A news has a large image vIew and long text description, which make the cell height relatively higher.

                              The text description is display by UILabel. If number of lines of the UILabel exceeds 7 lines, height of UILabel is fixed at 7 lines and “read more” button is shown to expand UILabel height and cell height.

                               

                              When you scroll the news cell and “read more” button is displayed in the middle of the iPhone screen, top of the cell is hidden at - (minus) Y axis. If you tap “read more” button, “reloadRows” behaves something wrong like my sample app.

                               

                              I would like to expand UILabel and the cell correctly when “read more” button is tapped.

                              Do you have any good code to realize this?

                               

                              I appreciate your support.

                                • Re: UITableView.reloadRows does not reload the target row.
                                  Claude31 Level 8 Level 8 (6,385 points)

                                  I should have been more precise. Reloading is for all, only redisplay is partial. Sorry for creating confusion.

                                   

                                  Instance Method reloadData()

                                   

                                  Reloads the rows and sections of the table view.

                                   

                                   


                                  Declaration

                                  func reloadData()

                                  Discussion

                                  Call this method to reload all the data that is used to construct the table, including cells, section headers and footers, index arrays, and so on. For efficiency, the table view redisplays only those rows that are visible. It adjusts offsets if the table shrinks as a result of the reload. The table view’s delegate or data source calls this method when it wants the table view to completely reload its data. It should not be called in the methods that insert or delete rows, especially within an animation block implemented with calls to beginUpdates() and endUpdates().

                                   

                                   

                                  To change the height when you tap the button in cell:

                                  - first, get the cell that contains the button (I copy from an existing project, did not test in this context, but should work)

                                  One way to do this is to explore all cells (in the button IBAction):

                                   

                                          if let cell = sender.superview?.superview {

                                              if let theTableView = cell.superview as? UITableView { // So, the button was in a cellView

                                                  for row in 0..<thetableview.numberofrows(insection: 0)="" {   // I assume there is a single section

                                                  let indexPath = IndexPath(row: row, section: 0)

                                                      if let cellAtRow = theTableView.cellForRow(at: indexPath) {    //  Will call didSelectRowAt

                                                             theTableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)     // Could scroll to position

                                   

                                   

                                  AndI tested by modifying slightly the code

                                   

                                  import UIKit
                                  
                                  class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
                                      @IBOutlet weak var aTableView: UITableView!
                                      var isTapped: Bool = false
                                      var selectedCellPath: IndexPath?          // NEW
                                      override func viewDidLoad() {
                                          super.viewDidLoad()
                                          aTableView.delegate = self
                                          aTableView.dataSource = self
                                      }
                                      func numberOfSections(in tableView: UITableView) -> Int {
                                          return 1
                                      }
                                      func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                                          return 50
                                      }
                                      func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
                                          print("heightForRowAt", indexPath, selectedCellPath)
                                          if selectedCellPath != nil && indexPath.row == selectedCellPath!.row { // 0 {     // CHANGED
                                              return 100.0
                                          }
                                          return 50.0
                                      }
                                      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                                          let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
                                          cell.textLabel!.text = "cell \(indexPath.row)"
                                  
                                          let backgroundView = UIView()
                                          backgroundView.backgroundColor = .red
                                          cell.selectedBackgroundView = backgroundView
                                  
                                          return cell
                                      }
                                      func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
                                          print("didSelectRowAt:", indexPath)
                                          isTapped = true
                                          selectedCellPath = indexPath
                                  
                                          tableView.reloadRows(at: [indexPath], with: .none)
                                          tableView.selectRow(at: indexPath, animated: true, scrollPosition: .middle)
                                      }
                                  
                                  }