วิธีหลีกเลี่ยง uicollectionview ยกเลิกการเลือกรายการทั้งหมดเมื่อมีการใช้สแนปชอตใหม่

เมื่อฉันโทร dataSource?.apply(snapshot, animatingDifferences: true) UICollectionView ที่เกี่ยวข้องจะยกเลิกการเลือกเซลล์ทั้งหมด

นี่เป็นปัญหาเมื่อได้รับข้อมูลใหม่ในพื้นหลัง เนื่องจากเมื่อมีการเปลี่ยนแปลงนี้ ผู้ใช้จะเห็นว่าการเลือกปัจจุบันหายไป

จะหลีกเลี่ยงการยกเลิกการเลือกรายการคอลเลกชันทั้งหมดเมื่อ apply(snapshot: animatingDifferences) ถูกเรียกได้อย่างไร


person AirXygène    schedule 04.05.2021    source แหล่งที่มา
comment
แน่นอนว่าส่วนใหญ่ขึ้นอยู่กับสิ่งที่คุณกำลังทำเพื่อระบุการเลือกให้กับผู้ใช้   -  person matt    schedule 04.05.2021
comment
@matt - พื้นหลังของเซลล์ถูกวาดด้วยสีอื่น ตามความเป็นจริงแล้วฉันใช้ UIBackgroundConfiguration แต่ฉันไม่คิดว่ามันจะเกี่ยวข้องกัน ก่อนนำไปใช้ (สแนปชอต :) การเลือก UICollectionView จะไม่ว่างเปล่า หลังจากการโทรแล้ว   -  person AirXygène    schedule 04.05.2021
comment
แน่นอนว่ามันเกี่ยวข้อง สิ่งที่ควรคิดกับตัวเองในที่นี้ก็คือ แนวคิดในการเลือกนั้นอิงตาม ข้อมูล อย่างเหมาะสม ไม่ใช่อิงตาม แถว คุณได้ตั้งค่าโค้ดที่ให้สีพื้นหลังแล้ว รหัสนั้นต้องระวังว่าข้อมูลนี้เป็นข้อมูลที่เลือกหรือไม่   -  person matt    schedule 04.05.2021
comment
ฉันใช้เวลาคิดอยู่พักหนึ่ง แต่ฉันคิดว่าฉันจะเก็บความคิดเห็นที่ต่างออกไป ข้อมูลการเลือกไม่ควรเป็นส่วนหนึ่งของโมเดล ฉันสามารถยอมรับว่ามันอยู่ระหว่างแบบจำลองและมุมมอง แต่นั่นทำให้เกิดปัญหาในการเก็บข้อมูลนั้นให้ตรงกันกับรายการเส้นทางดัชนีที่เลือกซึ่งเก็บไว้ในมุมมองคอลเลกชัน ฉันพบสาเหตุของปัญหา (ดูคำตอบ) และไม่เกี่ยวข้องกัน อย่างไรก็ตามฉันขอขอบคุณที่คุณพยายามช่วย ขอแสดงความนับถืออย่างสูง.   -  person AirXygène    schedule 10.05.2021


คำตอบ (1)


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

เมื่อใช้สแนปชอต การทำงานของ UICollectionViewDiffableDataSource จะแตกต่างกัน ไม่ว่า ItemIdentifierType จะเป็นประเภทค่าหรือประเภทการอ้างอิงก็ตาม

แน่นอนว่า ItemIdentifierType ของคุณจะต้องเป็นไปตาม Hashable แต่เมื่อโทร apply(snapshot, animatingDifferences: true):

  • หาก ItemIdentifierType เป็นประเภทค่า (struct) ดังนั้นฟังก์ชัน == และ hash ของมันจะถูกเรียกใช้เพื่อเปรียบเทียบรายการของสแน็ปช็อตที่ได้รับใหม่กับรายการของสแน็ปช็อตที่แสดงในปัจจุบัน ซึ่งช่วยให้ค้นหาส่วนต่าง เคลื่อนไหวความแตกต่าง และเก็บการเลือกไว้หากมี (ซึ่งเป็นปัญหาเดิมที่ฉันขอความช่วยเหลือ)
  • หาก ItemIdentifierType เป็นประเภทการอ้างอิง (คลาส) ฟังก์ชัน == และ hash ของมันจะ ไม่ เรียกว่า ซึ่งหมายความว่ารายการของสแน็ปช็อตใหม่และสแน็ปช็อตที่แสดงในปัจจุบันจะถูกเปรียบเทียบกับความเท่าเทียมกันในการอ้างอิงเปล่า (คือ พอยน์เตอร์เท่ากัน) ด้วยเหตุนี้ หากคุณสร้างรายการตั้งแต่ต้นด้วยอินสแตนซ์ใหม่ที่มีแฮชเดียวกัน การเปรียบเทียบจะเป็นเท็จเสมอ และคุณจะไม่ได้รับภาพเคลื่อนไหว และคุณจะสูญเสียการเลือก

วิธีแก้ไขง่ายๆ อย่างหนึ่งในสถานการณ์นี้คือการสรุปประเภทการอ้างอิงของคุณลงในโครงสร้าง ซึ่งจะส่งต่อ == และ hash ไปยังคลาส และใช้โครงสร้างนี้เป็น ItemIdentifierType

person AirXygène    schedule 10.05.2021