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
530
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
35
Swiftコンパイラ超入門+async関数の仕組み
shiz
0
270
複雑さに立ち向かうための ソフトウェア開発入門
shiz
3
1.7k
座談会 「Strict ConcurrencyとSwift 6が開く新時代: 私たちはどう生きるか?」
shiz
5
14k
(非公開スライド追加)座談会 「Strict ConcurrencyとSwift 6が開く新時代: 私たちはどう生きるか?」
shiz
1
570
複雑さに立ち向かうためのコードリーディング入門
shiz
35
14k
Swift Observation
shiz
5
830
Swift Reflection
shiz
1
240
Swift Concurrency Next Step
shiz
7
8.3k
Other Decks in Programming
See All in Programming
ペアプロ × 生成AI 現場での実践と課題について / generative-ai-in-pair-programming
codmoninc
0
230
Code as Context 〜 1にコードで 2にリンタ 34がなくて 5にルール? 〜
yodakeisuke
0
120
“いい感じ“な定量評価を求めて - Four Keysとアウトカムの間の探求 -
nealle
0
470
PHPでWebSocketサーバーを実装しよう2025
kubotak
0
240
プロダクト志向ってなんなんだろうね
righttouch
PRO
0
170
High-Level Programming Languages in AI Era -Human Thought and Mind-
hayat01sh1da
PRO
0
690
Hypervel - A Coroutine Framework for Laravel Artisans
albertcht
1
110
VS Code Update for GitHub Copilot
74th
1
550
Node-RED を(HTTP で)つなげる MCP サーバーを作ってみた
highu
0
120
『自分のデータだけ見せたい!』を叶える──Laravel × Casbin で複雑権限をスッキリ解きほぐす 25 分
akitotsukahara
1
600
0626 Findy Product Manager LT Night_高田スライド_speaker deck用
mana_takada
0
140
Create a website using Spatial Web
akkeylab
0
310
Featured
See All Featured
Designing Experiences People Love
moore
142
24k
Typedesign – Prime Four
hannesfritz
42
2.7k
Measuring & Analyzing Core Web Vitals
bluesmoon
7
500
BBQ
matthewcrist
89
9.7k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
29
9.5k
Build The Right Thing And Hit Your Dates
maggiecrowley
36
2.8k
KATA
mclloyd
30
14k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
44
2.4k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
138
34k
Thoughts on Productivity
jonyablonski
69
4.7k
Unsuck your backbone
ammeep
671
58k
Code Review Best Practice
trishagee
69
18k
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
͋Γ͕ͱ͏ ͍͟͝·ͨ͠ ը૾ࢀরϦϯΫ