Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
2019_9_18Reject.pdf
Search
[email protected]
September 18, 2019
Programming
3
520
2019_9_18Reject.pdf
iOS13の新しいAPIであるCompositional LayoutsとDiffable Data Sourcesについての発表です。
[email protected]
September 18, 2019
Tweet
Share
More Decks by
[email protected]
See All by
[email protected]
Swift compiler 101 & How async function works
shiz
0
32
Swiftコンパイラ超入門+async関数の仕組み
shiz
0
260
複雑さに立ち向かうための ソフトウェア開発入門
shiz
3
1.7k
座談会 「Strict ConcurrencyとSwift 6が開く新時代: 私たちはどう生きるか?」
shiz
5
14k
(非公開スライド追加)座談会 「Strict ConcurrencyとSwift 6が開く新時代: 私たちはどう生きるか?」
shiz
1
560
複雑さに立ち向かうためのコードリーディング入門
shiz
35
14k
Swift Observation
shiz
5
830
Swift Reflection
shiz
1
240
Swift Concurrency Next Step
shiz
7
8.2k
Other Decks in Programming
See All in Programming
Your Architecture as a Crime Scene:Forensic Analysis
manfredsteyer
PRO
0
100
つよそうにふるまい、つよい成果を出すのなら、つよいのかもしれない
irof
1
270
try-catchを使わないエラーハンドリング!? PHPでResult型の考え方を取り入れてみよう
kajitack
3
490
ワイがおすすめする新潟の食 / 20250530phpconf-niigata-eve
kasacchiful
0
300
ktr0731/go-mcpでMCPサーバー作ってみた
takak2166
0
150
単体テストの始め方/作り方
toms74209200
0
420
Gleamという選択肢
comamoca
6
670
無関心の谷
kanayannet
0
160
Beyond Portability: Live Migration for Evolving WebAssembly Workloads
chikuwait
0
330
Go Modules: From Basics to Beyond / Go Modulesの基本とその先へ
kuro_kurorrr
0
110
從零到一:搭建你的第一個 Observability 平台
blueswen
1
810
セキュリティマネジャー廃止とクラウドネイティブ型サンドボックス活用
kazumura
1
160
Featured
See All Featured
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.3k
Music & Morning Musume
bryan
46
6.6k
The World Runs on Bad Software
bkeepers
PRO
68
11k
Why Our Code Smells
bkeepers
PRO
337
57k
Agile that works and the tools we love
rasmusluckow
329
21k
Balancing Empowerment & Direction
lara
1
250
Building an army of robots
kneath
306
45k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
4
120
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
10
900
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
357
30k
We Have a Design System, Now What?
morganepeng
52
7.6k
The Art of Programming - Codeland 2020
erikaheidi
54
13k
Transcript
J04%$3FKFDU$POGFSFODF ࣌ͷมԽʹԠͯ͡ ਐԽ͢Δ $PMMFDUJPO7JFX ը૾ࢀরϦϯΫ
VISITS Technologiesגࣜձࣾ shiz@stzn3 shiz(ͣ͠) @shiz stzn(shiz) ։ൃܦݧݴޠ: Swift Kotlin Javascript
PHP C# Java Go… iOSDC Japan 2019 ίΞελοϑ
$PNQPTJUJPOBM-BZPVUT %J⒎BCMF%BUB4PVSDFT ը૾ࢀরϦϯΫ
$PNQPTJUJPOBM -BZPVUT ը૾ࢀরϦϯΫ
എܠ ը૾ࢀরϦϯΫ
J04ͷ"QQ4UPSF
None
None
6*$PMMFDUJPO7JFX -BZPVU நΫϥε υΩϡϝϯτ্ αϒΫϥε͕ඞཁ https://developer.apple.com/documentation/uikit/uicollectionviewlayout
6*$PMMFDUJPO7JFX 'MPX-BZPVU ߦϕʔεͷϨΠΞτ γϯϓϧͳઃఆ ڞ௨σβΠϯͰ෯͘ར༻
ϋʔυΣΞͷਐԽ ωοτϫʔΫͷ্ Ұͭͷը໘Ͱදࣔ͢Δ߲ͷ૿Ճ ϨΠΞτͷෳࡶԽ
ʑͷ ଟͷϘΠϥʔϓϨʔτ͕ඞཁ ύϑΥʔϚϯεͷߟྀ͕ඞཁ όονϔομʔɺϑολʔͷ ઃఆ͕ࠔ 4FMG4J[JOHͷܭࢉ͕ෳࡶ
$PNQPTJUJPOBM -BZPVUT খ͞ͳ෦ΛΈ߹ΘͤΔ ॊೈʹΧελϚΠζՄೳ ૣ͘ɺਖ਼֬ͳαΠζͷࣗಈܭࢉ
̐ͭͷཁૉ 4J[F
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
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
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
https://developer.apple.com/documentation/uikit/nscollectionlayoutitem 4J[FΛࢦఆ͢Δ $FMM)FBEFSɺ'PPUFSͳͲ
ϨΠΞτͷجຊ୯Ґ https://developer.apple.com/documentation/uikit/nscollectionlayoutgroup
*UFNͷͻͱ͔ͨ·Γ https://developer.apple.com/documentation/uikit/nscollectionlayoutgroup
ΫϩʔδϟͰॳظԽ https://developer.apple.com/documentation/uikit/nscollectionlayoutgroup
Ұͭͷ(SPVQΛࢦఆ (SPVQʹՃใΛࢦఆ https://developer.apple.com/documentation/uikit/nscollectionlayoutsection
https://developer.apple.com/documentation/uikit/uicollectionviewcompositionallayout https://developer.apple.com/documentation/appkit/nscollectionviewcompositionallayout
https://developer.apple.com/documentation/uikit/uicollectionviewcompositionallayout https://developer.apple.com/documentation/appkit/nscollectionviewcompositionallayout Ұͭͷ4FDUJPOΛࢦఆ
https://developer.apple.com/documentation/uikit/uicollectionviewcompositionallayout https://developer.apple.com/documentation/appkit/nscollectionviewcompositionallayout ΫϩʔδϟͰ 4FDUJPO͝ͱͷఆٛՄೳ
αϯϓϧίʔυ Ͱ֬ೝ
-JTU7JFX$POUSPMMFS
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 }
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ΛܾΊΔ
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Λ࡞Δ
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Λ࡞
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Λ࡞
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Λ࡞
(SJE7JFX$POUSPMMFS
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
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
(SJE7JFX$POUSPMMFS
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 ΞΠςϜΛʹࢦఆ ॎɺԣ
5XP$PMVNO7JFX$POUSPMMFS
DistinctSectionsViewController
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͝ͱʹ ϨΠΞτΛఆٛ
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ʹԠͯ͡ΧϥϜΛมߋ
ItemBadgeSupplementaryViewController
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
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Λ࡞
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ʹࢦఆ
ItemBadgeSupplementaryViewController
OrthogonalScrollingViewController
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
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ͷ εΫϩʔϧͷಈ͖ΛௐͰ͖Δ
OrthogonalScrollBehaviorViewController
%J⒎BCMF %BUB4PVSDFT
എܠ ը૾ࢀরϦϯΫ
%BUB 4PVSDF 6* OVNCFS0G4FDUJPOT OVNCFS0G*UFNT *O4FDUJPO DFMM'PS*UFN"U
%BUB 4PVSDF 6* EJE$IBOHF 8FC4FSWJDF 3FTQPOTF
%BUB 4PVSDF 6* <$FMM> <%BUB> *OEFY1BUI
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 ॱ൪Λؒҧ͑Δͱ ΤϥʔʹͳΔ߹
%J⒎BCMF %BUB4PVSDFT γϯϓϧͳ࣮ σʔλͷҰݩཧ ύϑΥʔϚϯεΛ࠷దԽ
/4%J⒎BCMF%BUB4PVSDF 4OBQTIPU 6*ͱσʔλΛཧ͢Δ།Ұͷଘࡏ 4JOHMF4PVSDFPG5SVUI *OEFY1BUIΛΘͳ͍ class NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType> where
SectionIdentifierType : Hashable, ItemIdentifierType : Hashable
αϯϓϧίʔυ Ͱ֬ೝ
.PVOUBJOT7JFX$POUSPMMFS
6*ͷߋ৽ εςοϓ func performQuery(with filter: String?) { let mountains =
mountainsController .filteredMountains(with: filter) .sorted { $0.name < $1.name } let snapshot = NSDiffableDataSourceSnapshot<Section, Mountain>() snapshot.appendSections([.main]) snapshot.appendItems(mountains) dataSource.apply(snapshot, animatingDifferences: true) } ͭͷεςοϓΛ౿Ή͚ͩͰઃఆ͕Ͱ͖Δ .PVOUBJOT7JFX$POUSPMMFS
func performQuery(with filter: String?) { let mountains = mountainsController .filteredMountains(with:
filter) .sorted { $0.name < $1.name } let snapshot = NSDiffableDataSourceSnapshot<Section, Mountain>() snapshot.appendSections([.main]) snapshot.appendItems(mountains) dataSource.apply(snapshot, animatingDifferences: true) } .PVOUBJOT7JFX$POUSPMMFS 1. ৽͍͠Snapshotͷੜ
func performQuery(with filter: String?) { let mountains = mountainsController.filteredMountains(with: filter)
.sorted { $0.name < $1.name } let snapshot = NSDiffableDataSourceSnapshot<Section, Mountain>() snapshot.appendSections([.main]) snapshot.appendItems(mountains) dataSource.apply(snapshot, animatingDifferences: true) } .PVOUBJOT7JFX$POUSPMMFS 2. ߋ৽͍ͨ͠ใͷՃ
func performQuery(with filter: String?) { let mountains = mountainsController.filteredMountains(with: filter)
.sorted { $0.name < $1.name } let snapshot = NSDiffableDataSourceSnapshot<Section, Mountain>() snapshot.appendSections([.main]) snapshot.appendItems(mountains) dataSource.apply( snapshot, animatingDifferences: true) } .PVOUBJOT7JFX$POUSPMMFS 3. applyͷݺͼग़͠
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
%BUB4PVSDFͷઃఆ func configureDataSource() { dataSource = UICollectionViewDiffableDataSource <Section, MountainsController.Mountain> (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
ΫϩʔδϟͰηϧͷઃఆํ๏Λࢦఆ func configureDataSource() { dataSource = UICollectionViewDiffableDataSource <Section, MountainsController.Mountain> (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
func configureDataSource() { dataSource = UICollectionViewDiffableDataSource <Section, MountainsController.Mountain> (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
8J'J4FUUJOHT7JFX$POUSPMMFS
ηΫγϣϯ͕ෳ͋Δ 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 ηΫγϣϯ͝ͱʹΛઃఆ͢Δ
*OTFSUJPO4PSU7JFX$POUSPMMFS
ඞཁͳͱ͜Ζ͚ͩߋ৽͢Δ 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
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
*OTFSUJPO4PSU7JFX$POUSPMMFS
ύϑΥʔϚϯε %J⒎ͷܭࢉ0 O BQQMZϝιουܭࢉ݁ՌΛϝΠ ϯΩϡʔͰฦ٫ ʹՃ࣮ෆཁͰόοΫάϥϯ υͰॲཧ͕Մೳ
·ͱΊ ը૾ࢀরϦϯΫ
એݴతͰ౷Ұతͳ"1* ϚϧνϓϥοτϑΥʔϜରԠ ϑϨʔϜϫʔΫͰཧ ڞ௨తͳಛ
ݕ౼͍͖͍ͯͨ͜͠ͱ ΧελϚΠζͲ͜·ͰՄೳʁ 4XJGU6*ͱͷ࿈ܞ
ͰJ04Ҏ߱ʜ
https://github.com/kishikawakatsumi/IBPCollectionViewCompositionalLayout *#1$PMMFDUJPO7JFX $PNQPTJUJPOBM-BZPVU
%J⒎BCMF%BUB4PVSDFT https://github.com/ra1028/DiffableDataSources
IUUQTRJJUBDPNTIJ[JUFNTBBCGFE
͋Γ͕ͱ͏ ͍͟͝·ͨ͠ ը૾ࢀরϦϯΫ