Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
2019_9_18Reject.pdf
Search
[email protected]
September 18, 2019
Programming
570
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
2019_9_18Reject.pdf
iOS13の新しいAPIであるCompositional LayoutsとDiffable Data Sourcesについての発表です。
[email protected]
September 18, 2019
More Decks by
[email protected]
See All by
[email protected]
TSPLのすすめ
shiz
1
360
Swift compiler 101 & How async function works
shiz
0
150
Swiftコンパイラ超入門+async関数の仕組み
shiz
0
390
複雑さに立ち向かうための ソフトウェア開発入門
shiz
3
2.5k
座談会 「Strict ConcurrencyとSwift 6が開く新時代: 私たちはどう生きるか?」
shiz
5
17k
(非公開スライド追加)座談会 「Strict ConcurrencyとSwift 6が開く新時代: 私たちはどう生きるか?」
shiz
1
820
複雑さに立ち向かうためのコードリーディング入門
shiz
35
15k
Swift Observation
shiz
5
960
Swift Reflection
shiz
1
310
Other Decks in Programming
See All in Programming
クラウドエージェントは、 何がそんなに便利なのか / what makes cloud agents so useful
rkaga
3
550
sbt 2.0: takeoff
eed3si9n
0
170
Compiling a real-world CLI tool to native with Static Hermes
tmikov2023
0
130
自サークルのIdPからログアウトできるようになるまで
taiseiue
1
150
No More NoSuchMethodError
exoego
1
110
contenteditable と日本語入力に向き合う
colorful12
0
220
コードで差別化できない時代の ソフトウェアエンジニアリング / Software Engineering in an Era Where Code Doesn’t Differentiate
kishida
2
200
APNsからLive Activityを開始する話
yumnumm
0
180
AIが生成したコードは読むべきか?抽象化設計とコードの品質保証 / abstraction-design-and-quality
minodriven
4
1.7k
Groovy as a human and AI friendly programming language
paulk
0
120
Python Lambdaにおけるテストしやすい設計とAI支援の活用 / Designing Testable Python Lambda Functions with AI
kitano_yuichi
1
200
Vue Fes Japan の “作る側”に関わってみて
naokihaba
1
190
Featured
See All Featured
Designing Experiences People Love
moore
143
24k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
3
3.9k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
230
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
580
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
1
640
Statistics for Hackers
jakevdp
799
230k
Optimising Largest Contentful Paint
csswizardry
37
4k
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
580
Become a Pro
speakerdeck
PRO
31
6.3k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Context Engineering - Making Every Token Count
addyosmani
9
1.2k
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
͋Γ͕ͱ͏ ͍͟͝·ͨ͠ ը૾ࢀরϦϯΫ