5000行のUITableViewを差分更新する / Difference update UITableView with 5000 rows

9bda8755a689204677a198ee85c0eb07?s=47 banjun
September 01, 2018

5000行のUITableViewを差分更新する / Difference update UITableView with 5000 rows

iOSDC Japan 2018s
2018/09/01 14:20〜 Track A レギュラートーク(30分)

CfP: https://fortee.jp/iosdc-japan-2018/proposal/530b6839-cc50-452c-9682-897afa9db18c

YouTube Archive: TBA

9bda8755a689204677a198ee85c0eb07?s=128

banjun

September 01, 2018
Tweet

Transcript

  1. ͹Μ͡ΎΜ!CBOKVO J04%$+BQBO ߦͷ6*5BCMF7JFXΛࠩ෼ߋ৽͢Δ

  2. ͹Μ͡ΎΜ!CBOKVO ࣗݾ঺հ 'MJDL4,,4,,ΩʔϘʔυ J04 -PWF-JWFSϥΠϒϑΥτੜ੒ NBD04 1IPUP4UVEJP1MBZFS
 ϥΠτχϯάΫϩϚΩʔΩϟϓνϟ NBD04 


    ΞΠϚεϋοΧιϯɾϓϦοΧιϯ NBD04ʙ ͱ͔
  3. ͓͠͝ͱ ͋ΒΏΔϞϊͷ؅ཧΛࢧԉ͢ΔΫϥ΢υαʔϏε ୨Է͠ ିग़͠ 1PDLFU

  4. https://nrstudy.connpass.com ΋͘΋͘ձ΍ͬͯ·͢ ฏ೔໷ ݄

  5. ࠓ೔࿩͢͜ͱ ୈ̍෦
 6*5BCMF7JFXͰࠩ෼ߋ৽ ୈ̎෦
 ύϑΥʔϚϯεղੳ

  6. ࠓ೔࿩͢͜ͱ "5BCMF7JFXࠩ෼ߋ৽΍ͬͯΔ  "6*ͷࠩ෼ߋ৽ͬͯͲΜͳ΋ͷ͔஌ͬͯΔ 
 ࡢ೔ͷࠩ෼ߋ৽ͷ࿩͖͍ͨ ͦͷલʹɾɾɾ͢͜͠Ξϯέʔτ

  7. 6*5BCMF7JFXͰࠩ෼ߋ৽Λ࢖͓͏ ୈ̍෦

  8. 6*5BCMF7JFX ߦ਺͕ͨ͘͞Μʹͳͬͯ΋଎͍ 6*7JFXγϦʔζͷͳ͔Ͱ͍ͪ͹Μ޷͖

  9. 6*5BCMF7JFXͷߋ৽खஈ શ෦ߋ৽ ࠩ෼ߋ৽ reloadData() deleteRows(at:with:) insertRows(at:with:) ʹ࢖͑Δϝιου [IndexPath] ͔ΜͨΜʂ Ξχϝʔγϣϯͳ͠ʂ

    ͍ͨ΁Μ
  10. reloadData() શ෦ߋ৽ ࠩ෼ߋ৽ deleteRows(at:with:) insertRows(at:with:)

  11. ࠩ෼ߋ৽ΛͲ͏࣮ݱ͢Δ͔ ࠩ෼ͷ[IndexPath]Λৗʹਖ਼֬ʹࢦఆ͢Δ͚ͩɾɾɾ ࡟আૢ࡞ͨ͠ߦ
 ϑΟϧλʔͰফ͑ͨߦ
 ϑΟϧλʔղআͰ࠶౓දࣔ͢Δߦ ߋ৽લޙͷσʔλͷEJGGΛऔΕΔͳΒɺ΋ͬͱͣͬͱ؆୯ʹͳΔ

  12. ࠩ෼ߋ৽ΛͲ͏࣮ݱ͢Δ͔ ࠩ෼ͷ[IndexPath]Λৗʹਖ਼֬ʹࢦఆ͢Δ͚ͩɾɾɾ ࡟আૢ࡞ͨ͠ߦ
 ϑΟϧλʔͰফ͑ͨߦ
 ϑΟϧλʔղআͰ࠶౓දࣔ͢Δߦ EJGGΛ࢖͓͏ લޙͷσʔλΛΈͯɺEJGGͰ<*OEFY1BUI>ग़͢

  13. EJ⒎ͱQBUDIBQQMZ insertRows(…) deleteRows(…) EJGG QBUDIBQQMZ old new ❌ ❌ ❌

    + %BUB4PVSDF
  14. ࠩ෼ߋ৽͸͕͍͍͜͜ ΩϨΠͰ෼͔Γ΍͍͢Ξχϝʔγϣϯ σʔλૢ࡞Ͱ*OEFY1BUIΛؾʹ͠ͳ͍ͰࡁΉ

  15. طଘΞϓϦ ࠩ෼ߋ৽ ଟ਺ߦΛѻ͏طଘΞϓϦ΋ɺ
 ͦΖͦΖࠩ෼ߋ৽ʹͯ͠ɺ
 ָͯ͠ΩϨΠʹΞχϝʔγϣϯ͍ͨ͠ʂʂʂ

  16. طଘΞϓϦ˞Πϝʔδ ฤूͰ͖Δ
 ը໘ ௥ՃͰ͖Δ
 ը໘

  17. ࠩ෼ߋ৽͍ΕͯΈͨ private var filteredSections: [Section] = [] { didSet {

    tableView.reloadData() } }
  18. ࠩ෼ߋ৽͍ΕͯΈͨ private var filteredSections: [Section] = [] { didSet {

    tableView.animateRowAndSectionChanges( oldData: oldValue, newData: filteredSections) } }
  19. ߦͰ࡟আͱϑΟϧλʔ ಛʹϑΟϧλʔ஗͗͢ͳ͍ɾɾɾ  P0 ͖ͬ͞ͷ͸ເͩͬͨͷ͔ ࠩ෼ߋ৽͍ΕͯΈͨ

  20. SFMPBE%BUBͷ΄͏͕Ϛγ ʜͱݴΘΕͳ͍ͨΊʹ

  21. ύϑΥʔϚϯεղੳ͠Α͏ ୈ̎෦

  22. ύϑΥʔϚϯεղੳ͠Α͏ " " # /4-PH $ צ

  23. ύϑΥʔϚϯεղੳ͠Α͏ ܭଌͰ͖ͳ͍΋ͷ͸վળͰ͖ͳ͍

  24. 5JNF1SPpMFSΛ͔ͭ͏

  25. 5JNF1SPpMFSͰΘ͔Δ͜ͱ ΞϓϦ࣮ߦதͷ$16ෛՙͷ࣌ܥྻͷάϥϑ ֤εϨουͰɺͲͷఔ౓ͷෛՙ͕͔͋ͬͨ ελοΫτϨʔεͷ֤ஈͷෛՙ ͔͔ͬͨ࣌ؒ

  26. 5JNF1SPpMFSͰΘ͔Δ͜ͱ ΞϓϦ࣮ߦதͷ$16ෛՙͷ࣌ܥྻͷάϥϑ ֤εϨουͰɺͲͷఔ౓ͷෛՙ͕͔͋ͬͨ ελοΫτϨʔεͷ֤ஈͷෛՙ ͔͔ͬͨ࣌ؒ

  27. 5JNF1SPpMFSͰΘ͔Δ͜ͱ ΞϓϦ࣮ߦதͷ$16ෛՙͷ࣌ܥྻͷάϥϑ ֤εϨουͰɺͲͷఔ౓ͷෛՙ͕͔͋ͬͨ ελοΫτϨʔεͷ֤ஈͷෛՙ ͔͔ͬͨ࣌ؒ

  28. ߋ৽׬ྃ·Ͱͷ߹ܭ࣌ؒ UPUBMT EJGG QBUDI ˞3FMFBTFCVJME ߦˠߦ

  29. ߋ৽׬ྃ·Ͱ վྑޙ UPUBMT EJGG QBUDI ˞τϨʔυΦϑ͋Γ ߦˠߦ

  30. ͲΕ͘Β͍ɺ஗͍ ׈Β͔ͳΞχϝʔγϣϯ GQT T
 'JSFCBTFͷʮ஗͍ϨϯμϦϯάʯT ͕Ҏ্  'JSFCBTFͷʮϑϦʔζͨ͠ϑϨʔϜʯT ͕Ҏ্ T

    T ͜ͷ͋ͨΓʹऩΊ͍ͨ
  31. ࠩ෼ߋ৽ϥΠϒϥϦ ػೳɾ଎౓ɾطଘઃܭ΁ͷӨڹ౓͕ҟͳΔ %XJGGUʜɹɹߦن໛Ͱ͸ϝϞϦ֬อͰ͖ͳ͍ %JGGFSʜɹɹEJGG଎౓͕΍΍஗͍ )FDLFM%JGG %FFQ%JGG %BUB4PVSDFT 3Y%BUB4PVSDFT ϚϧνηΫγϣϯඇରԠ ઃܭมߋ͕ඞཁ

  32. $PMMFDUJPOJOEFY struct Section<Item: Equatable>: Collection { var header: String? var

    items: [Item] // Diffable var diffIdentifier: AnyHashable // Collection var startIndex: Int {return items.startIndex} var endIndex: Int {return items.endIndex} subscript(position: Int) -> Item {return items[position]} func index(after i: Int) -> Int {return items.index(after: i)} }
  33. $PMMFDUJPOJOEFY ruct Section<Item: Equatable>: Collection { var header: String? var

    items: [Item] // Diffable var diffIdentifier: AnyHashable // Collection
  34. $16΄΅ͰT௒͑ $PMMFDUJPOJOEFY

  35. *OTUSVNFOUTجຊίϚϯυ ➡ɹ⬇ɹ➡ɹ⬇ɹ➡ɹ⬇ɹ➡ɹ⬇ɹ $PMMFDUJPOJOEFY

  36. JOEFYऔಘʹNJOɾɾɾ⁉ $PMMFDUJPOJOEFY

  37. $PMMFDUJPOJOEFYͷܭࢉྔ JOEFY͸3BOEPN"DDFTT$PMMFDUJPOͳΒఆ਺࣌ؒ0  
 ͦ͏Ͱͳ͚Ε͹ઢܗ࣌ؒ0 / /// - Complexity: O(1)

    if the collection conforms to /// `RandomAccessCollection`; otherwise, O(*k*), where *k* is the absolute /// value of `distance`. func index(_ i: Index, offsetBy distance: Int) -> Index swift/stdlib/public/core/Collection.swift
  38. 3BOEPN"DDFTT$PMMFDUJPOΛ࢖͓͏ ˠUPUBMTऑʹͳΔ ͍͍ͩͨഒߴ଎Խ extension Section: RandomAccessCollection {}

  39. 4FDUJPO*UFN&RVBUBCMF struct Section<Item: Equatable>: RandomAccessCollection { var header: String? var

    items: [Item] // Diffable var diffIdentifier: AnyHashable // Collection var startIndex: Int {return items.startIndex} var endIndex: Int {return items.endIndex} subscript(position: Int) -> Item {return items[position]} func index(after i: Int) -> Int {return items.index(after: i)} }
  40. $PMMFDUJPO@GBJM&BSMZ3BOHF$IFDLͰ ➡ɹ⬇ɹ➡ɹ⬇ɹ➡TXJGU@HFU(FOFSJD.FUBEBUB 4FDUJPO*UFN&RVBUBCMF

  41. $PMMFDUJPO@GBJM&BSMZ3BOHF$IFDLͰ ➡ɹ⬇ɹ➡ɹ⬇ɹ➡TXJGU@HFU(FOFSJD.FUBEBUB 4FDUJPO*UFN&RVBUBCMF

  42. (FOFSJDTΛআڈ͠Α͏ ˠUPUBMTʹͳΔ ͍͍ͩͨഒߴ଎Խ  @GBJM&BSMZ3BOHF$IFDL͸ؙ͝ͱফ͑Δ ಾ struct Section: RandomAccessCollection {

  43. QBUDIBQQMZ ͜Ε·Ͱͷख๏ͰɺQBUDIͷ࣌ؒ͸มԽ͠ͳ͍ T T T ߦ਺มԽ T T ख๏ Gen

    Rnd Gen Rnd Gen Rnd Gen Rnd
  44. QBUDIBQQMZ ͜Ε·Ͱͷख๏ͰɺQBUDIͷ࣌ؒ͸มԽ͠ͳ͍ ߦ ਺ ม Խ ผ ͷ EJGG
 ϥΠ

    ϒϥ Ϧ
  45. ࡟আΞχϝʔγϣϯੜ੒ @TFUVQ"OJNBUJPOT'PS%FMFUFE$FMMT͕ϘτϧωοΫʹͳΓ͕ͪ ΞχϝʔγϣϯແޮԽͰ͸ޮՌ͕ͳ͍ ❌QFSGPSN8JUIPVU"OJNBUJPO❌EJTBCMF"DUJPOT

  46. ࡟আΞχϝʔγϣϯੜ੒ @TFUVQ"OJNBUJPOT'PS%FMFUFE$FMMT͕ϘτϧωοΫʹͳΓ͕ͪ ΞχϝʔγϣϯແޮԽͰ͸ޮՌ͕ͳ͍ ❌QFSGPSN8JUIPVU"OJNBUJPO❌EJTBCMF"DUJPOT

  47. ૠೖ਺࡟আ਺ ૠೖ਺͸૿͑ͯ΋଎౓ʹ Өڹ͠ͳ͍ ࡟আ਺͕૿͑Δͱ஗͍ ߦʙΛѻ͏ͷ͸
 ͦ΋ͦ΋ݫ͍͠

  48. SFMPBE%BUBͷ΄͏͕ྑ͍ͷͰ͸ ʜͦ͏͍͏ʮͱ͖ʯ΋͋Δ

  49. ࠩ෼ߋ৽ͱଟ਺ߦ࡟আͷڞଘ ΄ͱΜͲͷࠩ෼ߋ৽ϥΠϒϥϦʹద༻Մೳ JOUFSSVQUΫϩʔδϟͰ෼ذͰ͖ΔϥΠϒϥϦ΋͋Δ EJGG QBUDIBQQMZ SFMPBE%BUB ଟ਺࡟আ

  50. ࠩ෼ߋ৽ͱଟ਺ߦ࡟আͷڞଘ ಘΔ΋ͷ ᮢ஋Λ௒͑ͨͱ͖ͷ QBUDIͷ଎౓T ഒߴ଎Խ  ˰UPUBMT ഒߴ଎Խ  ࣦͳ͏΋ͷ

    ᮢ஋Λ௒͑ͨͱ͖ͷ Ξχϝʔγϣϯ
  51. ࣍ͷεςοϓ "࠷ѱϛϦඵͳΒ0,ͱ͢Δ #EJGGΛ΋ͬͱ଎͘͢Δ $ϑΥʔϧόοΫͷӨڹΛݮΒ͢ ͦ͏͍͏ϥΠϒϥϦ͕
 ͋Ε͹ʜ

  52. EJ⒎Λ΋ͬͱ଎͘͢Δ %JGGFSͷEJGGΑΓ)FDLFMΞϧΰϦζϜ͕଎͍ͷ͸෼͔͍ͬͯΔ ϚϧνηΫγϣϯͷѻ͍͸஫ҙ ࠩ෼ߋ৽ͭ͘ΔͳΒʜ

  53. ϑΥʔϧόοΫͷӨڹΛݮΒ͢ ςʔϒϧશମͰʮࠩ෼ߋ৽PSreloadDataʯ ΑΓ΋ ηΫγϣϯ͝ͱʹʮࠩ෼ߋ৽PSreloadSectionsʯ ଟ਺࡟আͷηΫγϣϯʹר͖ࠐ·Εͣࠩ෼ߋ৽Ͱ͖Δ ͜Ε΋஗͘ͳΒͳ͍

  54. ηΫγϣϯ͝ͱʹSFMPBEGBMMCBDL͢Δ
 ࠩ෼ߋ৽ϥΠϒϥϦ ҆қʹGBMMCBDL͢Δίϯηϓτ࣮૷CBOKVO#JH%JGGFS ηΫγϣϯ͝ͱʹEJGG ηΫγϣϯ·͕ͨͳ͍  ߋ৽લʹදࣔ͞Ε͍ͯͳ͍ηΫγϣϯ͸SFMPBE4FDUJPOT -JTU%JGGͰEJGGܭࢉ )FDLFM 

    ଟ਺࡟আ͕͋ΔͳΒSFMPBE4FDUJPOT
  55. ߋ৽׬ྃ·Ͱ վྑޙ UPUBMT EJGG QBUDI ߦˠߦ EJGG QBUDI ߦˠߦ UPUBMT

  56. ·ͱΊ ࠩ෼ߋ৽͸Ξχϝʔγϣϯ΋ϩδοΫ΋ΩϨΠ كʹɺ͘͢͝஗͍έʔε͕͋ΔͷͰ஫ҙ ਺ߦͷ௥Ճ࡟আ͚ͩͰ͸ͳ͘ʮ΄ͱΜͲ࡟আʯ΋ݟ͓ͯ͜͏ EJGGΛ଎͘ɺQBUDIBQQMZΛ஗ͤͣ͘ɺշదͳࠩ෼ߋ৽

  57. None