Slide 1

Slide 1 text

J04%$3FKFDU$POGFSFODF ࣌୅ͷมԽʹԠͯ͡ ਐԽ͢Δ $PMMFDUJPO7JFX ը૾ࢀরϦϯΫ

Slide 2

Slide 2 text

VISITS Technologiesגࣜձࣾ shiz@stzn3 shiz(ͣ͠) @shiz stzn(shiz) ։ൃܦݧݴޠ: Swift Kotlin Javascript PHP C# Java Go… iOSDC Japan 2019 ίΞελοϑ

Slide 3

Slide 3 text

$PNQPTJUJPOBM-BZPVUT %J⒎BCMF%BUB4PVSDFT ը૾ࢀরϦϯΫ

Slide 4

Slide 4 text

$PNQPTJUJPOBM -BZPVUT ը૾ࢀরϦϯΫ

Slide 5

Slide 5 text

എܠ ը૾ࢀরϦϯΫ

Slide 6

Slide 6 text

J04ͷ"QQ4UPSF

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

6*$PMMFDUJPO7JFX -BZPVU ந৅Ϋϥε υΩϡϝϯτ্ αϒΫϥε͕ඞཁ https://developer.apple.com/documentation/uikit/uicollectionviewlayout

Slide 10

Slide 10 text

6*$PMMFDUJPO7JFX 'MPX-BZPVU ߦϕʔεͷϨΠΞ΢τ γϯϓϧͳઃఆ ڞ௨σβΠϯͰ෯޿͘ར༻

Slide 11

Slide 11 text

ϋʔυ΢ΣΞͷਐԽ ωοτϫʔΫ଎౓ͷ޲্ Ұͭͷը໘Ͱදࣔ͢Δ߲໨ͷ૿Ճ ϨΠΞ΢τͷෳࡶԽ

Slide 12

Slide 12 text

਺ʑͷ໰୊ ଟ਺ͷϘΠϥʔϓϨʔτ͕ඞཁ ύϑΥʔϚϯεͷߟྀ͕ඞཁ όον΍ϔομʔɺϑολʔͷ ઃఆ͕ࠔ೉ 4FMG4J[JOHͷܭࢉ͕ෳࡶ

Slide 13

Slide 13 text

$PNQPTJUJPOBM -BZPVUT খ͞ͳ෦඼Λ૊Έ߹ΘͤΔ ॊೈʹΧελϚΠζՄೳ ૣ͘ɺਖ਼֬ͳαΠζͷࣗಈܭࢉ

Slide 14

Slide 14 text

̐ͭͷཁૉ 4J[F

Slide 15

Slide 15 text

class NSCollectionLayoutDimension { class func fractionalWidth(_ fractionalWidth: CGFloat) -> Self class func fractionalHeight(_ fractionalHeight: CGFloat) -> Self } ਌ͷίϯϙʔωϯτͷ αΠζʹର͢Δׂ߹Ͱࢦఆ /4$PMMFDUJPO-BZPVU4J[F https://developer.apple.com/documentation/uikit/nscollectionlayoutsize

Slide 16

Slide 16 text

class NSCollectionLayoutDimension { class func absolute(_ absoluteDimension: CGFloat) -> Self class func estimated(_ estimatedDimension: CGFloat) -> Self } ϙΠϯτͰࢦఆ /4$PMMFDUJPO-BZPVU4J[F https://developer.apple.com/documentation/uikit/nscollectionlayoutsize

Slide 17

Slide 17 text

class NSCollectionLayoutDimension { class func absolute(_ absoluteDimension: CGFloat) -> Self class func estimated( _ estimatedDimension: CGFloat) -> Self } /4$PMMFDUJPO-BZPVU4J[F https://developer.apple.com/documentation/uikit/nscollectionlayoutsize

Slide 18

Slide 18 text

https://developer.apple.com/documentation/uikit/nscollectionlayoutitem 4J[FΛࢦఆ͢Δ $FMM΍)FBEFSɺ'PPUFSͳͲ

Slide 19

Slide 19 text

ϨΠΞ΢τͷجຊ୯Ґ https://developer.apple.com/documentation/uikit/nscollectionlayoutgroup

Slide 20

Slide 20 text

*UFNͷͻͱ͔ͨ·Γ https://developer.apple.com/documentation/uikit/nscollectionlayoutgroup

Slide 21

Slide 21 text

ΫϩʔδϟͰॳظԽ https://developer.apple.com/documentation/uikit/nscollectionlayoutgroup

Slide 22

Slide 22 text

Ұͭͷ(SPVQΛࢦఆ (SPVQʹ௥Ճ৘ใΛࢦఆ https://developer.apple.com/documentation/uikit/nscollectionlayoutsection

Slide 23

Slide 23 text

https://developer.apple.com/documentation/uikit/uicollectionviewcompositionallayout https://developer.apple.com/documentation/appkit/nscollectionviewcompositionallayout

Slide 24

Slide 24 text

https://developer.apple.com/documentation/uikit/uicollectionviewcompositionallayout https://developer.apple.com/documentation/appkit/nscollectionviewcompositionallayout Ұͭͷ4FDUJPOΛࢦఆ

Slide 25

Slide 25 text

https://developer.apple.com/documentation/uikit/uicollectionviewcompositionallayout https://developer.apple.com/documentation/appkit/nscollectionviewcompositionallayout ΫϩʔδϟͰ 4FDUJPO͝ͱͷఆٛ΋Մೳ

Slide 26

Slide 26 text

αϯϓϧίʔυ Ͱ֬ೝ

Slide 27

Slide 27 text

-JTU7JFX$POUSPMMFS

Slide 28

Slide 28 text

private func createLayout() -> UICollectionViewLayout { let itemSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem( layoutSize: itemSize) let groupSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(44)) let group = NSCollectionLayoutGroup.horizontal( layoutSize: groupSize, subitems: [item]) let section = NSCollectionLayoutSection( group: group) let layout = UICollectionViewCompositionalLayout( section: section) return layout }

Slide 29

Slide 29 text

private func createLayout() -> UICollectionViewLayout { let itemSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem( layoutSize: itemSize) let groupSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(44)) let group = NSCollectionLayoutGroup.horizontal( layoutSize: groupSize, subitems: [item]) let section = NSCollectionLayoutSection( group: group) let layout = UICollectionViewCompositionalLayout( section: section) return layout } ᶃ4J[FΛܾΊΔ

Slide 30

Slide 30 text

private func createLayout() -> UICollectionViewLayout { let itemSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem( layoutSize: itemSize) let groupSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(44)) let group = NSCollectionLayoutGroup.horizontal( layoutSize: groupSize, subitems: [item]) let section = NSCollectionLayoutSection( group: group) let layout = UICollectionViewCompositionalLayout( section: section) return layout } ᶄ4J[FΛࢦఆͯ͠*UFNΛ࡞Δ

Slide 31

Slide 31 text

private func createLayout() -> UICollectionViewLayout { let itemSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem( layoutSize: itemSize) let groupSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(44)) let group = NSCollectionLayoutGroup.horizontal( layoutSize: groupSize, subitems: [item]) let section = NSCollectionLayoutSection( group: group) let layout = UICollectionViewCompositionalLayout( section: section) return layout } ᶅ4J[Fͱ*UFNΛࢦఆͯ͠ (SPVQΛ࡞੒

Slide 32

Slide 32 text

private func createLayout() -> UICollectionViewLayout { let itemSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem( layoutSize: itemSize) let groupSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(44)) let group = NSCollectionLayoutGroup.horizontal( layoutSize: groupSize, subitems: [item]) let section = NSCollectionLayoutSection( group: group) let layout = UICollectionViewCompositionalLayout( section: section) return layout } ᶆ(SPVQΛࢦఆͯ͠ 4FDUJPOΛ࡞੒

Slide 33

Slide 33 text

private func createLayout() -> UICollectionViewLayout { let itemSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem( layoutSize: itemSize) let groupSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(44)) let group = NSCollectionLayoutGroup.horizontal( layoutSize: groupSize, subitems: [item]) let section = NSCollectionLayoutSection( group: group) let layout = UICollectionViewCompositionalLayout( section: section) return layout } ᶇ4FDUJPOΛࢦఆͯ͠ -BZPVUΛ࡞੒

Slide 34

Slide 34 text

(SJE7JFX$POUSPMMFS

Slide 35

Slide 35 text

private func createLayout() -> UICollectionViewLayout { let itemSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(0.2), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem(layoutSize: itemSize) let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.2), heightDimension: .fractionalWidth(1.0)) let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item]) let section = NSCollectionLayoutSection(group: group) let layout = UICollectionViewCompositionalLayout(section: section) return layout } ॎˋɺԣˋ (SJE7JFX$POUSPMMFS

Slide 36

Slide 36 text

private func createLayout() -> UICollectionViewLayout { let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.2), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem(layoutSize: itemSize) let groupSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(0.2)) let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item]) let section = NSCollectionLayoutSection(group: group) let layout = UICollectionViewCompositionalLayout(section: section) return layout } ॎʹԣͷˋ (SJE7JFX$POUSPMMFS

Slide 37

Slide 37 text

(SJE7JFX$POUSPMMFS

Slide 38

Slide 38 text

func createLayout() -> UICollectionViewLayout { let itemSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem(layoutSize: itemSize) let groupSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(44)) let group = NSCollectionLayoutGroup.horizontal( layoutSize: groupSize, subitem: item, count: 2) let spacing = CGFloat(10) group.interItemSpacing = .fixed(spacing) let section = NSCollectionLayoutSection(group: group) section.interGroupSpacing = spacing section.contentInsets = NSDirectionalEdgeInsets( top: 0, leading: 10, bottom: 0, trailing: 10) let layout = UICollectionViewCompositionalLayout(section: section) return layout } 5XP$PMVNO7JFX$POUSPMMFS ΞΠςϜ਺Λʹࢦఆ ॎɺԣ

Slide 39

Slide 39 text

5XP$PMVNO7JFX$POUSPMMFS

Slide 40

Slide 40 text

DistinctSectionsViewController

Slide 41

Slide 41 text

func createLayout() -> UICollectionViewLayout { let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in guard let sectionLayoutKind = ɹ SectionLayoutKind(rawValue: sectionIndex) else { ɹɹ return nil ɹ} let columns = sectionLayoutKind.columnCount let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem(layoutSize: itemSize) item.contentInsets = NSDirectionalEdgeInsets(top: 2, leading: 2, bottom: 2, trailing: 2) let groupHeight = columns == 1 ? NSCollectionLayoutDimension.absolute(44) : NSCollectionLayoutDimension.fractionalWidth(0.2) let groupSize = NSCollectionLayoutSize( ɹɹɹɹɹɹɹɹɹɹɹɹɹ widthDimension: .fractionalWidth(1.0), heightDimension: groupHeight) let group = NSCollectionLayoutGroup.horizontal( layoutSize: groupSize, subitem: item, count: columns) let section = NSCollectionLayoutSection(group: group) section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20) return section } return layout } DistinctSectionsViewController 4FDUJPO͝ͱʹ ϨΠΞ΢τΛఆٛ

Slide 42

Slide 42 text

func createLayout() -> UICollectionViewLayout { let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in guard let sectionLayoutKind = ɹ SectionLayoutKind(rawValue: sectionIndex) else { ɹɹ return nil ɹ} let columns = sectionLayoutKind.columnCount let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem(layoutSize: itemSize) item.contentInsets = NSDirectionalEdgeInsets(top: 2, leading: 2, bottom: 2, trailing: 2) let groupHeight = columns == 1 ? NSCollectionLayoutDimension.absolute(44) : NSCollectionLayoutDimension.fractionalWidth(0.2) let groupSize = NSCollectionLayoutSize( ɹɹɹɹɹɹɹɹɹɹɹɹɹ widthDimension: .fractionalWidth(1.0), heightDimension: groupHeight) let group = NSCollectionLayoutGroup.horizontal( layoutSize: groupSize, subitem: item, count: columns) let section = NSCollectionLayoutSection(group: group) section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20) return section } return layout } DistinctSectionsViewController 4FDUJPOʹԠͯ͡ΧϥϜ਺Λมߋ

Slide 43

Slide 43 text

ItemBadgeSupplementaryViewController

Slide 44

Slide 44 text

func createLayout() -> UICollectionViewLayout { let badgeAnchor = NSCollectionLayoutAnchor( edges: [.top, .trailing], fractionalOffset: CGPoint(x: 0.3, y: -0.3)) let badgeSize = NSCollectionLayoutSize(widthDimension: .absolute(20), heightDimension: .absolute(20)) let badge = NSCollectionLayoutSupplementaryItem( layoutSize: badgeSize, elementKind: ItemBadgeSupplementaryViewController.badgeElementKind, containerAnchor: badgeAnchor) let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.25), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem(layoutSize: itemSize, supplementaryItems: [badge]) item.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5) let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(0.2)) let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item]) let section = NSCollectionLayoutSection(group: group) section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20) let layout = UICollectionViewCompositionalLayout(section: section) return layout } ItemBadgeSupplementaryViewController

Slide 45

Slide 45 text

func createLayout() -> UICollectionViewLayout { let badgeAnchor = NSCollectionLayoutAnchor(edges: [.top, .trailing], fractionalOffset: CGPoint(x: 0.3, y: -0.3)) let badgeSize = NSCollectionLayoutSize(widthDimension: .absolute(20), heightDimension: .absolute(20)) let badge = NSCollectionLayoutSupplementaryItem( layoutSize: badgeSize, elementKind: ItemBadgeSupplementaryViewController .badgeElementKind, containerAnchor: badgeAnchor) let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.25), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem(layoutSize: itemSize, supplementaryItems: [badge]) item.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5) let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(0.2)) let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item]) let section = NSCollectionLayoutSection(group: group) section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20) let layout = UICollectionViewCompositionalLayout(section: section) return layout } ItemBadgeSupplementaryViewController SupplementaryItemΛ࡞੒

Slide 46

Slide 46 text

func createLayout() -> UICollectionViewLayout { let badgeAnchor = NSCollectionLayoutAnchor(edges: [.top, .trailing], fractionalOffset: CGPoint(x: 0.3, y: -0.3)) let badgeSize = NSCollectionLayoutSize(widthDimension: .absolute(20), heightDimension: .absolute(20)) let badge = NSCollectionLayoutSupplementaryItem( layoutSize: badgeSize, elementKind: ItemBadgeSupplementaryViewController.badgeElementKind, containerAnchor: badgeAnchor) let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.25), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem( layoutSize: itemSize, supplementaryItems: [badge]) item.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5) let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(0.2)) let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item]) let section = NSCollectionLayoutSection(group: group) section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20) let layout = UICollectionViewCompositionalLayout(section: section) return layout } ItemBadgeSupplementaryViewController Itemʹࢦఆ

Slide 47

Slide 47 text

ItemBadgeSupplementaryViewController

Slide 48

Slide 48 text

OrthogonalScrollingViewController

Slide 49

Slide 49 text

func createLayout() -> UICollectionViewLayout { let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in let leadingItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.7), heightDimension: .fractionalHeight(1.0))) leadingItem.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10) let trailingItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(0.3))) trailingItem.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10) let trailingGroup = NSCollectionLayoutGroup.vertical(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.3), heightDimension: .fractionalHeight(1.0)), subitem: trailingItem, count: 2) let containerGroup = NSCollectionLayoutGroup.horizontal( layoutSize: NSCollectionLayoutSize( widthDimension: .fractionalWidth(0.85), heightDimension: .fractionalHeight(0.4)), subitems: [leadingItem, trailingGroup]) let section = NSCollectionLayoutSection(group: containerGroup) section.orthogonalScrollingBehavior = .continuous return section } return layout } (SPVQͷதʹ(SPVQΛೖΕΔ OrthogonalScrollingViewController

Slide 50

Slide 50 text

func createLayout() -> UICollectionViewLayout { let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in let leadingItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.7), heightDimension: .fractionalHeight(1.0))) leadingItem.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10) let trailingItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(0.3))) trailingItem.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10) let trailingGroup = NSCollectionLayoutGroup.vertical(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.3), heightDimension: .fractionalHeight(1.0)), subitem: trailingItem, count: 2) let containerGroup = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.85), heightDimension: .fractionalHeight(0.4)), subitems: [leadingItem, trailingGroup]) let section = NSCollectionLayoutSection( group: containerGroup) section.orthogonalScrollingBehavior = .continuous return section } return layout } OrthogonalScrollingViewController ωετ͞Εͨ(SPVQͷ εΫϩʔϧͷಈ͖Λௐ੔Ͱ͖Δ

Slide 51

Slide 51 text

OrthogonalScrollBehaviorViewController

Slide 52

Slide 52 text

%J⒎BCMF %BUB4PVSDFT

Slide 53

Slide 53 text

എܠ ը૾ࢀরϦϯΫ

Slide 54

Slide 54 text

%BUB 4PVSDF 6* OVNCFS0G4FDUJPOT OVNCFS0G*UFNT *O4FDUJPO DFMM'PS*UFN"U

Slide 55

Slide 55 text

%BUB 4PVSDF 6* EJE$IBOHF 8FC4FSWJDF 3FTQPOTF

Slide 56

Slide 56 text

%BUB 4PVSDF 6* <$FMM> <%BUB> *OEFY1BUI

Slide 57

Slide 57 text

QFSGPSN#BUDI6QEBUFT collectionView.performBatchUpdates({ var deletes = [Int]() var inserts = [(person:Person, index:Int)]() … for deletedIndex in deletes.sorted().reversed() { people.remove(at: deletedIndex) } let sortedInserts = inserts.sorted(by: { (personA, personB) -> Bool in return personA.index <= personB.index }) for insertion in sortedInserts { people.insert(insertion.person, at: insertion.index) } IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOVJLJUVJDPMMFDUJPOWJFXDVTUPNJ[JOH@DPMMFDUJPO@WJFX@MBZPVUT DIBOHFTMBUFTU@NJOPS ॱ൪Λؒҧ͑Δͱ ΤϥʔʹͳΔ৔߹΋

Slide 58

Slide 58 text

%J⒎BCMF %BUB4PVSDFT γϯϓϧͳ࣮૷ σʔλͷҰݩ؅ཧ ύϑΥʔϚϯεΛ࠷దԽ

Slide 59

Slide 59 text

/4%J⒎BCMF%BUB4PVSDF 4OBQTIPU 6*ͱσʔλΛ؅ཧ͢Δ།Ұͷଘࡏ 4JOHMF4PVSDFPG5SVUI *OEFY1BUIΛ࢖Θͳ͍ class NSDiffableDataSourceSnapshot where SectionIdentifierType : Hashable, ItemIdentifierType : Hashable

Slide 60

Slide 60 text

αϯϓϧίʔυ Ͱ֬ೝ

Slide 61

Slide 61 text

.PVOUBJOT7JFX$POUSPMMFS

Slide 62

Slide 62 text

6*ͷߋ৽ εςοϓ func performQuery(with filter: String?) { let mountains = mountainsController .filteredMountains(with: filter) .sorted { $0.name < $1.name } let snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([.main]) snapshot.appendItems(mountains) dataSource.apply(snapshot, animatingDifferences: true) } ͭͷεςοϓΛ౿Ή͚ͩͰઃఆ͕Ͱ͖Δ .PVOUBJOT7JFX$POUSPMMFS

Slide 63

Slide 63 text

func performQuery(with filter: String?) { let mountains = mountainsController .filteredMountains(with: filter) .sorted { $0.name < $1.name } let snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([.main]) snapshot.appendItems(mountains) dataSource.apply(snapshot, animatingDifferences: true) } .PVOUBJOT7JFX$POUSPMMFS 1. ৽͍͠Snapshotͷੜ੒

Slide 64

Slide 64 text

func performQuery(with filter: String?) { let mountains = mountainsController.filteredMountains(with: filter) .sorted { $0.name < $1.name } let snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([.main]) snapshot.appendItems(mountains) dataSource.apply(snapshot, animatingDifferences: true) } .PVOUBJOT7JFX$POUSPMMFS 2. ߋ৽͍ͨ͠৘ใͷ௥Ճ

Slide 65

Slide 65 text

func performQuery(with filter: String?) { let mountains = mountainsController.filteredMountains(with: filter) .sorted { $0.name < $1.name } let snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([.main]) snapshot.appendItems(mountains) dataSource.apply( snapshot, animatingDifferences: true) } .PVOUBJOT7JFX$POUSPMMFS 3. applyͷݺͼग़͠

Slide 66

Slide 66 text

4FDUJPO .PVOUBJO enum Section: CaseIterable { case main } struct Mountain: Hashable { let name: String let height: Int let identifier = UUID() func hash(into hasher: inout Hasher) { hasher.combine(identifier) } static func == (lhs: Mountain, rhs: Mountain) -> Bool { return lhs.identifier == rhs.identifier } } .PVOUBJOT7JFX$POUSPMMFS

Slide 67

Slide 67 text

%BUB4PVSDFͷઃఆ func configureDataSource() { dataSource = UICollectionViewDiffableDataSource (collectionView: mountainsCollectionView) { (collectionView: UICollectionView, indexPath: IndexPath, mountain: MountainsController.Mountain) -> UICollectionViewCell? in guard let mountainCell = collectionView.dequeueReusableCell( withReuseIdentifier: LabelCell.reuseIdentifier, for: indexPath) as? LabelCell else { fatalError("Cannot create new cell") } mountainCell.label.text = mountain.name return mountainCell } } .PVOUBJOT7JFX$POUSPMMFS

Slide 68

Slide 68 text

ΫϩʔδϟͰηϧ΁ͷઃఆํ๏Λࢦఆ func configureDataSource() { dataSource = UICollectionViewDiffableDataSource (collectionView: mountainsCollectionView) { (collectionView: UICollectionView, indexPath: IndexPath, mountain: MountainsController.Mountain) -> UICollectionViewCell? in guard let mountainCell = collectionView.dequeueReusableCell( withReuseIdentifier: LabelCell.reuseIdentifier, for: indexPath) as? LabelCell else { fatalError("Cannot create new cell") } mountainCell.label.text = mountain.name return mountainCell } } .PVOUBJOT7JFX$POUSPMMFS

Slide 69

Slide 69 text

func configureDataSource() { dataSource = UICollectionViewDiffableDataSource (collectionView: mountainsCollectionView) { (collectionView: UICollectionView, indexPath: IndexPath, mountain: MountainsController.Mountain) -> UICollectionViewCell? in guard let mountainCell = collectionView.dequeueReusableCell( withReuseIdentifier: LabelCell.reuseIdentifier, for: indexPath) as? LabelCell else { fatalError("Cannot create new cell") } mountainCell.label.text = mountain.name return mountainCell } } IndexPathΛ࢖༻͍ͯ͠ͳ͍ .PVOUBJOT7JFX$POUSPMMFS

Slide 70

Slide 70 text

8J'J4FUUJOHT7JFX$POUSPMMFS

Slide 71

Slide 71 text

ηΫγϣϯ͕ෳ਺͋Δ func updateUI(animated: Bool = true) { … currentSnapshot.appendSections([.config]) currentSnapshot.appendItems(configItems, toSection: .config) if controller.wifiEnabled { let sortedNetworks = controller.availableNetworks.sorted { $0.name < $1.name } let networkItems = sortedNetworks.map { Item(network: $0) } currentSnapshot.appendSections([.networks]) currentSnapshot.appendItems(networkItems, toSection: .networks) } self.dataSource.apply(currentSnapshot, animatingDifferences: animated) } 8J'J4FUUJOHT7JFX$POUSPMMFS ηΫγϣϯ͝ͱʹ஋Λઃఆ͢Δ

Slide 72

Slide 72 text

*OTFSUJPO4PSU7JFX$POUSPMMFS

Slide 73

Slide 73 text

ඞཁͳͱ͜Ζ͚ͩߋ৽͢Δ func performSortStep() { let updatedSnapshot = dataSource.snapshot() updatedSnapshot.sectionIdentifiers.forEach { let section = $0 if !section.isSorted { section.sortNext() let items = section.values updatedSnapshot.deleteItems(items) updatedSnapshot.appendItems(items, toSection: section) sectionCountNeedingSort += 1 } } … } ݱࡏͷ4OBQTIPUͷঢ়ଶΛऔಘ *OTFSUJPO4PSU7JFX$POUSPMMFS

Slide 74

Slide 74 text

func performSortStep() { let updatedSnapshot = dataSource.snapshot() updatedSnapshot.sectionIdentifiers.forEach { let section = $0 if !section.isSorted { section.sortNext() let items = section.values updatedSnapshot.deleteItems(items) updatedSnapshot.appendItems( items, toSection: section) sectionCountNeedingSort += 1 } } … } ඞཁͳͱ͜ΖͷΈߋ৽ *OTFSUJPO4PSU7JFX$POUSPMMFS

Slide 75

Slide 75 text

*OTFSUJPO4PSU7JFX$POUSPMMFS

Slide 76

Slide 76 text

ύϑΥʔϚϯε %J⒎ͷܭࢉ͸0 O BQQMZϝιου͸ܭࢉ݁ՌΛϝΠ ϯΩϡʔͰฦ٫ ʹ௥Ճ࣮૷ෆཁͰόοΫάϥ΢ϯ υͰॲཧ͕Մೳ

Slide 77

Slide 77 text

·ͱΊ ը૾ࢀরϦϯΫ

Slide 78

Slide 78 text

એݴతͰ౷Ұతͳ"1* ϚϧνϓϥοτϑΥʔϜରԠ ϑϨʔϜϫʔΫͰ؅ཧ ڞ௨తͳಛ௃

Slide 79

Slide 79 text

ݕ౼͍͖͍ͯͨ͜͠ͱ ΧελϚΠζ͸Ͳ͜·ͰՄೳʁ 4XJGU6*ͱͷ࿈ܞ

Slide 80

Slide 80 text

Ͱ΋J04Ҏ߱ʜ

Slide 81

Slide 81 text

https://github.com/kishikawakatsumi/IBPCollectionViewCompositionalLayout *#1$PMMFDUJPO7JFX $PNQPTJUJPOBM-BZPVU

Slide 82

Slide 82 text

%J⒎BCMF%BUB4PVSDFT https://github.com/ra1028/DiffableDataSources

Slide 83

Slide 83 text

IUUQTRJJUBDPNTIJ[JUFNTBBCGFE

Slide 84

Slide 84 text

͋Γ͕ͱ͏ ͍͟͝·ͨ͠ ը૾ࢀরϦϯΫ