reloadData () ของ UITableView พร้อมความสูงของเซลล์แบบไดนามิกทำให้เกิดการเลื่อนที่น่ากลัว


142

ฉันรู้สึกว่านี่อาจเป็นปัญหาทั่วไปและสงสัยว่ามีวิธีแก้ไขปัญหาร่วมกันหรือไม่

โดยพื้นฐานแล้ว UITableView ของฉันมีความสูงของเซลล์แบบไดนามิกสำหรับทุกเซลล์ หากฉันไม่ได้อยู่ที่ด้านบนของ UITableView และฉันการtableView.reloadData()เลื่อนขึ้นจะกลายเป็นสิ่งที่น่ากลัว

ฉันเชื่อว่านี่เป็นเพราะความจริงที่ว่าเพราะฉันโหลดข้อมูลใหม่ขณะที่ฉันเลื่อนขึ้น UITableView กำลังคำนวณความสูงใหม่สำหรับแต่ละเซลล์ที่มองเห็นได้ ฉันจะลดขนาดนั้นได้อย่างไรหรือฉันจะโหลดเฉพาะข้อมูลจาก IndexPath ที่แน่นอนไปยังจุดสิ้นสุดของ UITableView ได้อย่างไร

นอกจากนี้เมื่อฉันจัดการเพื่อเลื่อนไปด้านบนสุดฉันสามารถเลื่อนกลับลงมาและจากนั้นขึ้นไม่มีปัญหาโดยไม่มีการกระโดด สิ่งนี้มีโอกาสมากที่สุดเนื่องจากมีการคำนวณความสูงของ UITableViewCell แล้ว


สิ่งคู่ ... (1) reloadRowsAtIndexPathsใช่แน่นอนคุณสามารถโหลดแถวบางอย่างที่ใช้ แต่ (2) คุณหมายถึงอะไรโดย "jumpy" และ (3) คุณตั้งค่าความสูงแถวโดยประมาณอย่างไร (เพียงแค่พยายามที่จะคิดออกว่ามีทางออกที่ดีกว่าที่จะช่วยให้คุณสามารถปรับปรุงตารางแบบไดนามิก.)
Lyndsey สกอตต์

@LyndseyScott ใช่ฉันได้ตั้งค่าความสูงของแถวโดยประมาณแล้ว โดย jumpy ฉันหมายความว่าเมื่อฉันเลื่อนขึ้นแถวจะเลื่อนขึ้น ฉันเชื่อว่าเป็นเพราะฉันตั้งค่าความสูงแถวที่ประมาณไว้ที่ 128 จากนั้นเมื่อฉันเลื่อนขึ้นโพสต์ทั้งหมดของฉันใน UITableView มีขนาดเล็กลงดังนั้นจึงลดความสูงลงทำให้ตารางของฉันกระโดด ฉันกำลังคิดที่จะทำ reloadRowsAtIndexPaths จากแถวหนึ่งxไปยังแถวสุดท้ายใน TableView ของฉัน ... แต่เนื่องจากฉันกำลังแทรกแถวใหม่มันไม่ทำงานฉันไม่ทราบว่าจุดสิ้นสุดของมุมมองตารางของฉันจะเป็นอย่างไรก่อนที่ฉันจะโหลดใหม่ ข้อมูล.
เดวิด

2
@LyndseyScott ยังฉันไม่สามารถแก้ปัญหาได้มีวิธีแก้ปัญหาที่ดีหรือไม่
rad

1
คุณเคยพบวิธีแก้ปัญหาสำหรับปัญหานี้หรือไม่? ฉันประสบปัญหาเดียวกันกับที่เห็นในวิดีโอของคุณ
user3344977

1
ไม่มีคำตอบด้านล่างสำหรับฉัน
Srujan Simha

คำตอบ:


221

เพื่อป้องกันการกระโดดคุณควรบันทึกความสูงของเซลล์เมื่อโหลดและให้ค่าที่แน่นอนในtableView:estimatedHeightForRowAtIndexPath:

สวิฟท์:

var cellHeights = [IndexPath: CGFloat]()

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    cellHeights[indexPath] = cell.frame.size.height
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return cellHeights[indexPath] ?? UITableView.automaticDimension
}

วัตถุประสงค์ C:

// declare cellHeightsDictionary
NSMutableDictionary *cellHeightsDictionary = @{}.mutableCopy;

// declare table dynamic row height and create correct constraints in cells
tableView.rowHeight = UITableViewAutomaticDimension;

// save height
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    [cellHeightsDictionary setObject:@(cell.frame.size.height) forKey:indexPath];
}

// give exact height value
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSNumber *height = [cellHeightsDictionary objectForKey:indexPath];
    if (height) return height.doubleValue;
    return UITableViewAutomaticDimension;
}

1
ขอบคุณคุณประหยัดวันของฉันจริงๆ :) ทำงานใน objc ด้วย
Artem Z.

3
อย่าลืมที่จะเริ่มต้นcellHeightsDictionary: cellHeightsDictionary = [NSMutableDictionary dictionary];
Gerharbo

1
estimatedHeightForRowAtIndexPath:ส่งคืนค่า double อาจทำให้เกิด*** Assertion failure in -[UISectionRowData refreshWithSection:tableView:tableViewRowData:]ข้อผิดพลาด เพื่อแก้ไขreturn floorf(height.floatValue);แทน
liushuaikobe

สวัสดี @lgor ฉันมีปัญหาเดียวกันและพยายามใช้โซลูชันของคุณ ปัญหาที่ฉันได้รับคือการประมาณความสูงของพื้นผิวได้รับการเรียกก่อนที่จะแสดงความคมชัดดังนั้นความสูงของเซลล์จะไม่ถูกคำนวณเมื่อเรียกความสูงโดยประมาณ ความช่วยเหลือใด ๆ
Madhuri

1
@ ความสูงที่มีประสิทธิภาพของมาหะริควรคำนวณใน "heightForRowAtIndexPath" ซึ่งถูกเรียกใช้สำหรับทุกเซลล์บนหน้าจอก่อนหน้านี้ willDisplayCell ซึ่งจะตั้งค่าความสูงในพจนานุกรมเพื่อใช้ในภายหลังโดยประมาณRowHeight (บนรีโหลดตาราง)
Donnit

109

คำตอบที่ยอมรับในเวอร์ชัน Swift 3

var cellHeights: [IndexPath : CGFloat] = [:]


func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    cellHeights[indexPath] = cell.frame.size.height
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return cellHeights[indexPath] ?? 70.0 
}

ขอบคุณมันใช้งานได้ดี! ในความเป็นจริงฉันสามารถลบการใช้งานของฉัน func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {นี้จัดการการคำนวณความสูงทั้งหมดที่ฉันต้องการ
Natalia

หลังจากที่ต้องดิ้นรนหลายชั่วโมงด้วยการกระโดดอย่างต่อเนื่องฉันคิดว่าฉันลืมที่UITableViewDelegateจะเพิ่มชั้นเรียนของฉัน สอดคล้องกับโปรโตคอลนั้นเป็นสิ่งจำเป็นเพราะมันมีwillDisplayฟังก์ชั่นที่แสดงไว้ข้างต้น ฉันหวังว่าฉันสามารถช่วยคนที่ต่อสู้ดิ้นรนแบบเดียวกัน
MJQZ1347

ขอบคุณสำหรับคำตอบอย่างรวดเร็ว ในกรณีของฉันฉันมีพฤติกรรมที่แปลกประหลาดบางอย่างของเซลล์ที่ออกคำสั่งโหลดซ้ำเมื่อมุมมองตารางถูกเลื่อนไปที่ / ใกล้ด้านล่าง ฉันจะใช้สิ่งนี้นับจากนี้ไปทุกครั้งที่ฉันมีเซลล์ที่ปรับขนาดตัวเอง
Trev14

ทำงานได้อย่างสมบูรณ์แบบใน Swift 4.2
Adam S.

ช่วยชีวิต มีประโยชน์มากเมื่อพยายามเพิ่มรายการเพิ่มเติมในแหล่งข้อมูล ป้องกันการกระโดดของเซลล์ที่เพิ่งเพิ่มเข้าไปตรงกลางของหน้าจอ
Philip Borbon

38

การกระโดดเป็นเพราะความสูงโดยประมาณที่ไม่ดี ยิ่งความสูงต่ำโดยประมาณแตกต่างจากความสูงจริงตารางก็อาจกระโดดได้มากขึ้นเมื่อมีการโหลดซ้ำโดยเฉพาะยิ่งเลื่อนลงด้านล่างมากขึ้น นี่เป็นเพราะขนาดโดยประมาณของตารางแตกต่างจากขนาดจริงอย่างมากบังคับให้ตารางปรับขนาดเนื้อหาและออฟเซ็ต ดังนั้นความสูงโดยประมาณไม่ควรเป็นค่าสุ่ม แต่ใกล้กับสิ่งที่คุณคิดว่าความสูงนั้นจะเป็น ฉันเคยมีประสบการณ์เมื่อฉันตั้งค่าUITableViewAutomaticDimension ถ้าเซลล์ของคุณเป็นประเภทเดียวกันแล้ว

func viewDidLoad() {
     super.viewDidLoad()
     tableView.estimatedRowHeight = 100//close to your cell height
}

หากคุณมีความหลากหลายของเซลล์ในส่วนต่าง ๆ ฉันคิดว่าที่ที่ดีกว่าคือ

func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
     //return different sizes for different cells if you need to
     return 100
}

2
ขอบคุณมันเป็นเหตุผลที่ tableView ของฉันน่ากลัวมาก
Louis de Decker

1
คำตอบเก่า แต่ยังคงเกิดขึ้นจริง ณ ปีพ. ศ. 2561 ซึ่งแตกต่างจากคำตอบอื่น ๆ ทั้งหมดคำตอบนี้แสดงการตั้งค่าโดยประมาณแถวสูงหนึ่งครั้งใน viewDidLoad ซึ่งช่วยเมื่อเซลล์มีความสูงเท่ากันหรือใกล้เคียงกันมาก Thanx BTW หรือ esimatedRowHeight สามารถตั้งค่าผ่านตัวสร้างส่วนต่อประสานในตัวตรวจสอบขนาด> มุมมองตาราง> ประมาณ
Vitalii

หากความสูงโดยประมาณที่แม่นยำยิ่งขึ้นช่วยฉันได้ ฉันยังมีสไตล์การดูตารางหลายส่วนที่จัดกลุ่มและต้องดำเนินการtableView(_:estimatedHeightForHeaderInSection:)
nteissler

25

@Igorคำตอบทำงานได้ดีในกรณีนี้Swift-4รหัสของมัน

// declaration & initialization  
var cellHeightsDictionary: [IndexPath: CGFloat] = [:]  

ในวิธีการดังต่อไปนี้ UITableViewDelegate

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
  // print("Cell height: \(cell.frame.size.height)")
  self.cellHeightsDictionary[indexPath] = cell.frame.size.height
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
  if let height =  self.cellHeightsDictionary[indexPath] {
    return height
  }
  return UITableView.automaticDimension
}

6
วิธีจัดการกับการแทรก / การลบแถวโดยใช้โซลูชันนี้ TableView กระโดดเนื่องจากข้อมูลพจนานุกรมไม่ได้เกิดขึ้นจริง
Alexey Chekanov

1
ใช้งานได้ดี! โดยเฉพาะอย่างยิ่งในเซลล์สุดท้ายเมื่อโหลดแถวใหม่
Ning

19

ฉันลองแก้ไขปัญหาทั้งหมดข้างต้นแล้ว แต่ไม่มีอะไรทำงาน

หลังจากใช้เวลาหลายชั่วโมงและผ่านความผิดหวังที่เป็นไปได้ทั้งหมดให้หาวิธีแก้ไขปัญหานี้ วิธีนี้เป็นวิธีช่วยชีวิต! ทำงานเหมือนจับใจ!

สวิฟต์ 4

let lastContentOffset = tableView.contentOffset
tableView.beginUpdates()
tableView.endUpdates()
tableView.layer.removeAllAnimations()
tableView.setContentOffset(lastContentOffset, animated: false)

ฉันเพิ่มมันเป็นส่วนเสริมเพื่อให้โค้ดดูสะอาดตาและหลีกเลี่ยงการเขียนบรรทัดเหล่านี้ทุกครั้งที่ฉันต้องการโหลดซ้ำ

extension UITableView {

    func reloadWithoutAnimation() {
        let lastScrollOffset = contentOffset
        beginUpdates()
        endUpdates()
        layer.removeAllAnimations()
        setContentOffset(lastScrollOffset, animated: false)
    }
}

ในที่สุด ..

tableView.reloadWithoutAnimation()

หรือคุณสามารถเพิ่มบรรทัดเหล่านี้ในUITableViewCell awakeFromNib()วิธีการของคุณ

layer.shouldRasterize = true
layer.rasterizationScale = UIScreen.main.scale

และทำตามปกติ reloadData()


1
มันจะทำการรีโหลดอย่างไร? คุณเรียกมันว่าreloadWithoutAnimationแต่reloadส่วนไหนของมัน
ด้าน

@ แมทคุณสามารถโทรหาtableView.reloadData()ก่อนแล้วtableView.reloadWithoutAnimation()ก็ยังใช้งานได้
Srujan Simha

ที่ดี! ไม่มีข้อใดถูกใช้กับฉันได้ แม้แต่ความสูงและความสูงโดยประมาณก็เท่ากัน น่าสนใจ
TY Kucuk

1
ไม่ทำงานสำหรับฉัน มันผิดพลาดที่ tableView.endUpdates () ใครช่วยฉันได้!
คาคาชิ

12

ฉันใช้วิธีเพิ่มเติมในการแก้ไข:

สำหรับตัวควบคุมมุมมอง:

var cellHeights: [IndexPath : CGFloat] = [:]


func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    cellHeights[indexPath] = cell.frame.size.height
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return cellHeights[indexPath] ?? 70.0 
}

เป็นส่วนขยายสำหรับ UITableView

extension UITableView {
  func reloadSectionWithouAnimation(section: Int) {
      UIView.performWithoutAnimation {
          let offset = self.contentOffset
          self.reloadSections(IndexSet(integer: section), with: .none)
          self.contentOffset = offset
      }
  }
}

ผลที่ได้คือ

tableView.reloadSectionWithouAnimation(section: indexPath.section)

1
กุญแจสำคัญสำหรับฉันคือการใช้ส่วนขยาย UITableView ของเขาที่นี่ ฉลาดมาก. ขอบคุณ rastislv
BennyTheNerd

ทำงานได้อย่างสมบูรณ์แบบ แต่มีข้อเสียเปรียบเพียงข้อเดียวคุณสูญเสียแอนิเมชั่นเมื่อใส่หัวกระดาษท้ายกระดาษหรือแถว
Soufian Hossam

จะโหลดซ้ำส่วนไหนภาพเคลื่อนไหวจะถูกเรียกว่าอย่างไร ตัวอย่างเช่นผู้ใช้สามารถโพสต์ภาพในแอพของฉัน (เช่น Instagram); ฉันสามารถปรับขนาดรูปภาพได้ แต่ในกรณีส่วนใหญ่ฉันต้องเลื่อนเซลล์ตารางออกมาเพื่อความสนุกที่จะเกิดขึ้น ฉันต้องการให้เซลล์มีขนาดที่ถูกต้องเมื่อตารางผ่าน reloadData
ลุค Irvin

11

ฉันวิ่งเข้าไปในนี้วันนี้และสังเกต:

  1. เป็น iOS 8 เท่านั้นแน่นอน
  2. การเขียนทับcellForRowAtIndexPathไม่ได้ช่วยอะไร

การแก้ไขนั้นง่ายมาก:

แทนที่estimatedHeightForRowAtIndexPathและตรวจสอบให้แน่ใจว่าส่งคืนค่าที่ถูกต้อง

ด้วยสิ่งนี้การกระวนกระวายใจและการกระโดดไปรอบ ๆ ใน UITableViews ของฉันได้หยุดลง

หมายเหตุ: ฉันรู้ขนาดของเซลล์จริง มีเพียงสองค่าที่เป็นไปได้ หากเซลล์ของคุณมีขนาดผันแปรอย่างแท้จริงคุณอาจต้องการแคชcell.bounds.size.heightจากtableView:willDisplayCell:forRowAtIndexPath:


2
แก้ไขมันเมื่อมันมาแทนที่เมธอดHeightForRowAtIndexPathที่มีค่าสูงเช่น 300f
Flappy

1
@ Flappy เป็นเรื่องที่น่าสนใจว่าโซลูชันของคุณทำงานอย่างไรและสั้นกว่าเทคนิคที่แนะนำอื่น ๆ ลองโพสต์เป็นคำตอบ
Rohan Sanap

9

จริงๆแล้วคุณสามารถโหลดซ้ำบางแถวได้โดยใช้reloadRowsAtIndexPathsเช่น:

tableView.reloadRowsAtIndexPaths(indexPathArray, withRowAnimation: UITableViewRowAnimation.None)

แต่โดยทั่วไปคุณสามารถเคลื่อนไหวความสูงของเซลล์ตารางได้เช่น:

tableView.beginUpdates()
tableView.endUpdates()

ฉันได้ลองใช้วิธี startUpdates / endUpdates แล้ว แต่มันมีผลกับแถวที่มองเห็นในตารางเท่านั้น ฉันยังมีปัญหาเมื่อฉันเลื่อนขึ้น
เดวิด

@ David อาจเป็นเพราะคุณใช้ความสูงของแถวโดยประมาณ
Lyndsey Scott

ฉันควรกำจัด EstimatedRowHeights ของฉันและควรแทนที่ด้วย startUpdates และ endUpdates แทนหรือไม่
เดวิด

@ David คุณจะไม่ "แทนที่" อะไร แต่ขึ้นอยู่กับพฤติกรรมที่ต้องการ ... หากคุณต้องการใช้ความสูงของแถวโดยประมาณและเพียงแค่โหลดดัชนีด้านล่างส่วนที่มองเห็นในปัจจุบันของตารางคุณสามารถทำเช่นนั้นได้ ฉันบอกว่าใช้ reloadRowsAtIndexPaths
Lyndsey Scott

หนึ่งในปัญหาของฉันกับการลองใช้เมธอด reladRowsAtIndexPaths คือฉันกำลังใช้การเลื่อนแบบไม่ จำกัด ดังนั้นเมื่อฉันโหลดอีกครั้ง Data เป็นเพราะฉันเพิ่งเพิ่ม 15 แถวใน dataSource ซึ่งหมายความว่า indexPaths สำหรับแถวเหล่านั้นยังไม่มีอยู่ใน UITableView
David

3

นี่เป็นรุ่นที่สั้นกว่าเล็กน้อย:

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return self.cellHeightsDictionary[indexPath] ?? UITableViewAutomaticDimension
}


2

มีข้อผิดพลาดที่ฉันเชื่อว่าเปิดตัวใน iOS11

นั่นคือเมื่อคุณทำreloadtableView contentOffSetจะได้รับการเปลี่ยนแปลงโดยไม่คาดคิด ในความเป็นจริงcontentOffsetไม่ควรเปลี่ยนหลังจากโหลดซ้ำ มันมีแนวโน้มที่จะเกิดขึ้นเนื่องจากการผิดพลาดของUITableViewAutomaticDimension

คุณต้องบันทึกcontentOffSetและตั้งค่ากลับเป็นค่าที่บันทึกไว้หลังจากการโหลดซ้ำเสร็จสิ้น

func reloadTableOnMain(with offset: CGPoint = CGPoint.zero){

    DispatchQueue.main.async { [weak self] () in

        self?.tableView.reloadData()
        self?.tableView.layoutIfNeeded()
        self?.tableView.contentOffset = offset
    }
}

คุณใช้มันอย่างไร?

someFunctionThatMakesChangesToYourDatasource()
let offset = tableview.contentOffset
reloadTableOnMain(with: offset)

คำตอบนี้มาจากที่นี่


2

อันนี้ใช้ได้กับฉันใน Swift4:

extension UITableView {

    func reloadWithoutAnimation() {
        let lastScrollOffset = contentOffset
        reloadData()
        layoutIfNeeded()
        setContentOffset(lastScrollOffset, animated: false)
    }
}

1

ไม่มีวิธีแก้ปัญหาเหล่านี้สำหรับฉัน นี่คือสิ่งที่ฉันทำกับSwift 4 & Xcode 10.1 ...

ใน viewDidLoad () ประกาศความสูงของแถวแบบไดนามิกของตารางและสร้างข้อ จำกัด ที่ถูกต้องในเซลล์ ...

tableView.rowHeight = UITableView.automaticDimension

รวมทั้งใน viewDidLoad () ให้ลงทะเบียน tableView cell nibs ทั้งหมดของคุณไปยัง tableview ดังนี้:

tableView.register(UINib(nibName: "YourTableViewCell", bundle: nil), forCellReuseIdentifier: "YourTableViewCell")
tableView.register(UINib(nibName: "YourSecondTableViewCell", bundle: nil), forCellReuseIdentifier: "YourSecondTableViewCell")
tableView.register(UINib(nibName: "YourThirdTableViewCell", bundle: nil), forCellReuseIdentifier: "YourThirdTableViewCell")

ใน tableView heightForRowAt ให้ส่งคืนความสูงเท่ากับความสูงของแต่ละเซลล์ที่ indexPath.row ...

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

    if indexPath.row == 0 {
        let cell = Bundle.main.loadNibNamed("YourTableViewCell", owner: self, options: nil)?.first as! YourTableViewCell
        return cell.layer.frame.height
    } else if indexPath.row == 1 {
        let cell = Bundle.main.loadNibNamed("YourSecondTableViewCell", owner: self, options: nil)?.first as! YourSecondTableViewCell
        return cell.layer.frame.height
    } else {
        let cell = Bundle.main.loadNibNamed("YourThirdTableViewCell", owner: self, options: nil)?.first as! YourThirdTableViewCell
        return cell.layer.frame.height
    } 

}

ทีนี้ให้ความสูงของแถวโดยประมาณสำหรับแต่ละเซลล์ใน tableView ที่ประเมินไว้โดยความสูงของพื้น แม่นยำในขณะที่คุณสามารถ ...

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {

    if indexPath.row == 0 {
        return 400 // or whatever YourTableViewCell's height is
    } else if indexPath.row == 1 {
        return 231 // or whatever YourSecondTableViewCell's height is
    } else {
        return 216 // or whatever YourThirdTableViewCell's height is
    } 

}

ที่ควรจะทำงาน ...

ฉันไม่จำเป็นต้องบันทึกและตั้งค่า contentOffset เมื่อเรียก tableView.reloadData ()


1

ฉันมีความสูงของเซลล์ 2 แบบ

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        let cellHeight = CGFloat(checkIsCleanResultSection(index: indexPath.row) ? 130 : 160)
        return Helper.makeDeviceSpecificCommonSize(cellHeight)
    }

หลังจากที่ฉันเพิ่มความสูงโดยประมาณสำหรับแถวที่ไม่มีการกระโดดอีก

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    let cellHeight = CGFloat(checkIsCleanResultSection(index: indexPath.row) ? 130 : 160)
    return Helper.makeDeviceSpecificCommonSize(cellHeight)
}

0

พยายามที่จะเรียกร้องก่อนที่จะกลับเซลล์ในcell.layoutSubviews() func cellForRowAtIndexPath(_ indexPath: NSIndexPath) -> UITableViewCell?มันรู้จักบั๊กใน iOS8


0

คุณสามารถใช้สิ่งต่อไปนี้ใน ViewDidLoad()

tableView.estimatedRowHeight = 0     // if have just tableViewCells <br/>

// use this if you have tableview Header/footer <br/>
tableView.estimatedSectionFooterHeight = 0 <br/>
tableView.estimatedSectionHeaderHeight = 0

0

ฉันมีพฤติกรรมการกระโดดนี้และในขั้นต้นฉันสามารถลดความมันได้โดยการตั้งค่าความสูงส่วนหัวโดยประมาณที่แน่นอน (เพราะฉันมีมุมมองที่เป็นไปได้เพียง 1 มุมมองเท่านั้น) อย่างไรก็ตามการกระโดดเริ่มเกิดขึ้นภายในส่วนหัวโดยเฉพาะ

ตามคำตอบที่นี่ฉันมีเงื่อนงำว่ามันเกี่ยวข้องกับภาพเคลื่อนไหวดังนั้นฉันจึงพบว่ามุมมองตารางนั้นอยู่ในมุมมองแบบสแต็กและบางครั้งเราก็โทรstackView.layoutIfNeeded()เข้าไปในบล็อกแอนิเมชั่น ทางออกสุดท้ายของฉันคือการทำให้แน่ใจว่าการโทรนี้จะไม่เกิดขึ้นเว้นแต่จำเป็นต้องมี "จริงๆ" เพราะเลย์เอาต์ "ถ้าจำเป็น" มีพฤติกรรมการมองเห็นในบริบทนั้นแม้ว่า "ไม่จำเป็น"


0

ฉันมีปัญหาเดียวกัน ฉันมีเลขหน้าและโหลดซ้ำข้อมูลโดยไม่มีภาพเคลื่อนไหว แต่ก็ไม่ได้ช่วยให้เลื่อนเพื่อป้องกันการกระโดด ฉันมีขนาดแตกต่างกันของ IPhones การเลื่อนไม่น่ากลัวบน iphone8 แต่มันน่ากลัวใน iphone7 +

ฉันใช้การเปลี่ยนแปลงต่อไปนี้ในฟังก์ชั่นviewDidLoad :

    self.myTableView.estimatedRowHeight = 0.0
    self.myTableView.estimatedSectionFooterHeight = 0
    self.myTableView.estimatedSectionHeaderHeight = 0

และปัญหาของฉันแก้ไข ฉันหวังว่ามันจะช่วยคุณเช่นกัน


0

วิธีหนึ่งในการแก้ไขปัญหานี้ที่ฉันพบคือ

CATransaction.begin()
UIView.setAnimationsEnabled(false)
CATransaction.setCompletionBlock {
   UIView.setAnimationsEnabled(true)
}
tableView.reloadSections([indexPath.section], with: .none)
CATransaction.commit()

-2

จริง ๆ แล้วฉันพบว่าถ้าคุณใช้reloadRowsทำให้เกิดปัญหาการกระโดด จากนั้นคุณควรลองใช้reloadSectionsดังนี้:

UIView.performWithoutAnimation {
    tableView.reloadSections(NSIndexSet(index: indexPath.section) as IndexSet, with: .none)
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.