Several Tips to convert from RxDataSource
to NSDiffableDatasource & UICollectionView
potatotips #79
2022/10/31
Fumiya Sakai
自己紹介
・Fumiya Sakai
・Freelance App Engineer
アカウント:
・Twitter: https://twitter.com/fumiyasac
・Facebook: https://www.facebook.com/fumiya.sakai.37
・Github: https://github.com/fumiyasac
・Qiita: https://qiita.com/fumiyasac@github
発表者:
・Born on September 21, 1984
これまでの歩み:
Web Designer
2008 ~ 2010
Web Engineer
2012 ~ 2016
App Engineer
2017 ~ Now
iOS / Android / sometimes Flutter
iOSのUI実装本を執筆しています!
書籍に掲載したサンプルのバージョンアップや続編等に現在着手中です。
少しの工夫で実現できるTIPS集やライブラリ表現の活用集をはじめとした、iOSア
プリ開発の中でも特にUI実装やUIKitを利用した画面の中で特徴を与える様な表現
という題材に焦点を当てた書籍となっております。
現在は電子書籍版のみとなります。 こちらは全て¥1,000となっております。
https://just1factory.booth.pm/
概要:
https://book-tech.com/
価格:
📖 Booth
📖 Book Tech
UI実装であると嬉しいレシピブックの最新情報
UI実装であると嬉しいレシピブックVol.3として昨年10月に商業化しました!
Still
WIP
これまでの同人誌として頒布したものに加えて、Vol.1及びVol.2に頒布したものの
中で書籍に載せきれなかったものや表現や動きが特徴的でユーザーにもほんの少し
遊び心を与える様なUI実装を紹介したものをVol.3としています。
概要:
これからの構想:
こちらで購入可能です:
Amazon / Google Play / Apple Books / KINOKUNIYA / Rakuten BOOKS etc..
🏊 iOS: SwiftUIを利用したUI実装や動画関連の実装
🏊 Android: Jetpack Composeの基本やその他気になるUI表現の考察
今回のスライドにつきまして
業務や個人開発でRxDataSourceからDiffableDataSourceへのリプレイスを実施
RxDataSourceを利用した処理を置き換えていく部分を中心にご紹介をできればと思います。
1. RxDataSource&RxSwiftベースの実装においてDiffableDataSource部分だけを置き換えていきたい:
RxDataSource&RxSwiftベースでも画面処理には差し支えがないものの、iOS14以降であればDiffableDataSourceでの差分更新は
もちろんCellRegistrationを利用したCellの生成処理も活用可能である点は魅力に感じていました。
2. UICollectionViewCompositionalLayoutへの布石とする:
実はDiffableDataSourceを利用していたとしても従来通りのUICollectionViewDelegateLayoutを利用することはできるものの、
UICollectionViewCompositionalLayoutを利用する方が画面構造的にもシンプルに済ませられるケースも多そうでした。
3. 置き換えを進めていくにあたって考え方を変える必要がある部分もあった:
最初は結構似ているかもしれないと思っていたけれども、しっかりと見ていくと実は意外と落とし穴があって見事にハマった
り、想定以上に時間を要してしまった部分もありました(ここは私自身がRxDataSourceをあまり使わなかったため)。
RxDataSourceに関する簡単な概要紹介
RxSwift&UITableView・UICollectionViewでの実装を便利にする優れもの
(参考)RxDataSource: https://www.fabrizioduroni.it/2020/04/19/dependecy-injection-swift/
RxDataSourceで構築された画面の置き換え方針
一番のポイントとなる部分はDataSourceやCell要素構築に関する部分
1. DataSource部分の乗せ替え対応:
必要に応じてRxSwiftベースで作られているMVVMまたはMVPのViewModelやPresenter側の処理に変更が必要となる。
2. 従来のLayout処理をUICollectionViewCompositionalLayoutへの乗せ替え対応:
UICollectionViewCompositionalLayoutの宣言的なLayout構成を活用する事でよりシンプルな形になるよう変更する。
アプリのTOP画面の様に1つの画面に多くのSectionがある画面を対応する際はまずはここを完璧に整える事を目標に!
補足. HorizontalなCarousel表現について:
UICollectionViewCompositionalLayoutでは特にUICollectionViewを入れ子にしなくて
も実現可能(そうでなければUICollectionView in UICollectionViewCellの形) スクロール可能
👉 Cellへ表示データを渡す際に少しだけ形を変形する必要があります。
RxDataSource用のSectionType・ItemType定義
SectionType・ItemTypeのcaseがUICollectionViewCellと密接に関係する
enum TopSectionType {
case banner(title: String)
case featured(headerViewObject: TopHeaderView.HeaderViewObject)
case news(headerViewObject: TopHeaderView.HeaderViewObject)
case discount(title: String)
case photo(headerViewObject: TopHeaderView.HeaderViewObject)
}
typealias TopSection = SectionModel<TopSectionType, TopItemType>
Banner Header:
スクロール可能
Featured Carousel: News:
enum TopItemType {
case banner(bannerViewObject: TopBannerCell.CellViewObject)
case featured(featuredViewObjects: [TopFeaturedCell.CellViewObject])
case news(newsViewObject: TopNewsCell.CellViewObject)
case discount(discountViewObject: TopDiscountCell.CellViewObject)
case photo(photoViewObject: TopPhotoCell.CellViewObject)
} ※HorizontalScroll部分は中にUICollectionViewがある
… Cell要素1つ分
let items = BehaviorRelay<[TopSection]>(value: [])
1. Enum定義をしてcase内のassociated valueに表示データを定義する :
2. RxDataSource用のTypealias定義とViewControllerでCell要素とバインドする処理用の変数を準備 :
RxDataSourceで構築された画面処理に関するポイント
必要なSectionModelの内容を決めて、それが変化すると画面に反映される形
※ Header/Footer要素の構築に関してもconfigureSupplementaryViewの部分で構築する形となる
typealias TopSection = SectionModel<TopSectionType, TopItemType>
ViewController側におけるCell生成処理の抜粋 :
private lazy var dataSource = RxCollectionViewSectionedReloadDataSource<TopSection>(
configureCell: configureCell,
configureSupplementaryView: configureSupplementaryView
)
private lazy var configureCell: RxCollectionViewSectionedReloadDataSource<TopSection>
.ConfigureCell = { [weak self] (_, collectionView, indexPath, itemType) in
guard let strongSelf = self else { return UICollectionViewCell() }
switch itemType {
case .banner(let bannerViewObject):
// バナー表示用のCell要素を生成する処理を記載する
case .featured(let featuredViewObjects):
// 水平カルーセル表示用のCell要素を生成する処理を記載する
…(必要なCell要素の生成をitemTypeの条件分岐に合わせて生成していく)…
}
}
viewModel = TopViewModel()
viewModel.items
.asDriver()
.drive(collectionView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
RxSwiftでの処理
ViewModel内の処理で変数itemの内容が更新さ
れたタイミングでDataSourceのClosure内部に
定義しているCell・SupplementaryViewの生成
処理が実行されて、画面に内容が反映される
let items = BehaviorRelay<[TopSection]>(value: [])
※RxDataSourceで提供するSectionModel配列
Cell要素生成処理
DiffableDataSource用のSectionType・ItemType定義
SectionType・ItemTypeはHashableに準拠する必要がある点に注意!
enum TopSectionType: Hashable {
case banner(title: String)
case featured(headerViewObject: TopHeaderView.HeaderViewObject)
case news(headerViewObject: TopHeaderView.HeaderViewObject)
case discount(title: String)
case photo(headerViewObject: TopHeaderView.HeaderViewObject)
}
Banner Header:
スクロール可能
Featured Carousel: News:
enum TopItemType: Hashable {
case banner(bannerViewObject: TopBannerCell.CellViewObject)
case featured(featuredViewObject: TopFeaturedCell.CellViewObject)
case news(newsViewObject: TopNewsCell.CellViewObject)
case discount(discountViewObject: TopDiscountCell.CellViewObject)
case photo(photoViewObject: TopPhotoCell.CellViewObject)
} ※UICollectionViewCompositionalLayoutを利用する
… Cell要素1つ分
1. Enum定義をしてcase内のassociated valueに表示データを定義する :
2. Hash値を生成するために定義されているViewObjectのassociate valueの値を利用する :
Hash値が重複してしまうとCrashするのでCellViewObject・HeaderViewObjectの値はこの点には注意する必要があります。
DiffableDataSourceを利用する際のひと工夫
DiffableDataSourceのどの処理をどの責務で実行するかを考えてみる
1. DiffableDataSourceにまつわる処理をViewControllerで頑張りすぎない形にする :
DataSourceの構築とデータの反映・Cell要素の生成・画面レイアウト定義等、実は必要な処理がたくさんあります。
ViewController ViewModel UseCase・Repository Infrastructure
どこに置くべきか悩ましい😓 ViewModel側 : DiffableDataSource構築 ViewController側 : Layout定義やCell構築
2. AnyHashableで頑張りすぎない形にするための工夫 :
画面専用のDiffableDataSourceクラスを準備する事で定義したEnumと対応ができる様な形としておく。
private var dataSource: UICollectionViewDiffableDataSource<TopSectionType, AnyHashable>
extension TopViewController {
class TopDataSource: UICollectionViewDiffableDataSource<TopSectionType, TopItemType> {}
}
△
○
DataSourceとViewController・ViewModelが対応
できる様な形を作っておく点がポイント。
iOS14~利用可能なCellRegistrationにも対応する(1)
CellRegistrationの処理を行いやすい様にする拡張を定義する
protocol DynamicRegistrable: UICollectionViewCell {
associatedtype Item
static var cellNib: UINib { get }
static func makeCellRegistration() -> UICollectionView.CellRegistration<Self, Item>
func configure(_ cellViewObject: Item)
}
extension DynamicRegistrable {
static func makeCellRegistration() -> UICollectionView.CellRegistration<Self, Item> {
return .init(cellNib: cellNib, handler: { cell, _, item in
return cell.configure(item)
})
}
}
UICollectionViewクラスの拡張の応用することでEnumに定義したViewObjectと関連付ける :
extension NSObjectProtocol {
static var className: String {
return String(describing: self)
}
}
extension UICollectionView {
static func makeNibResource<T: UICollectionViewCell>(_ cellType: T.Type) -> UINib {
return UINib(nibName: T.identifier, bundle: nil)
}
}
extension UICollectionReusableView {
static var identifier: String {
return className
}
}
※ItemはItemTypeのassociated valueに対応
従来通りのUICollectionViewCellを作り、
DynamicRegistrableに準拠させる様にする。
※2. UINibのMappingにR.swift等も利用可能
※1. 今回はxibとクラス定義でCellを作る想定
※3. Item不要のCell・SupplementaryViewに
ついてもこの方法を応用することで定義
することができます。
iOS14~利用可能なCellRegistrationにも対応する(2)
CellRegistrationの拡張に準拠したCellクラスを定義する
該当するCell要素クラスに対してDynamicRegistrableに準拠させた場合の概要 :
final class TopBannerCell: UICollectionViewCell, DynamicRegistrable {
static let cellNib = UICollectionViewCell.makeNibResource(TopBannerCell.self)
typealias Item = CellViewObject
…(Cell表示のために必要な処理を記載する:@IBOutletや内部プロパティ等)…
func configure(_ item: Item) {
// バナー表示用のCell要素を表示する処理を記載する
}
}
extension TopBannerCell {
// TopItemTypeのassociated valueに定義するViewObjectの構造体定義
struct CellViewObject {
let id: Int
let identifier: String
let imageUrl: URL?
}
}
※CellのIdentifierからUINibを取得する
Cell要素生成処理 makeCellRegistration()と連動している部分になります。
ViewModel等DataSourceを作る部分で期待している処理
① ItemTypeがHashableに準拠するためのHash値を作成すること
② ItemTypeに応じたCell表示データを作成すること
ViewControllerにおけるCell要素構築処理の概要
CellRegistrationを利用したCellの生成処理の例
private func configureTopV2DataSource() {
let topBannerCellRegistration = TopBannerCell.makeCellRegistration()
let topFeaturedCellRegistration = TopFeaturedCell.makeCellRegistration()
…(表示する必要がある分だけCellRegistrationを追加する)…
topDataSource = TopDataSource(collectionView: collectionView) { [weak self] (collectionView, indexPath, itemType) -> UICollectionViewCell? in
guard let self = self else { return UICollectionViewCell() }
switch itemType {
case .banner(let bannerViewObject):
let cell = collectionView.dequeueConfiguredReusableCell(using: topBannerCellRegistration, for: indexPath, item: bannerViewObject)
return cell
case .featured(let featuredViewObject):
let cell = collectionView.dequeueConfiguredReusableCell(using: topFeaturedCellRegistration, for: indexPath, item: featuredViewObject)
return cell
…(表示する必要がある分だけCell生成処理を追加する)…
}
}
}
private var topDataSource: TopDataSource!
topDataSource.supplementaryViewProvider = { … } を利用する形になります。
ViewController側におけるCell生成処理の抜粋 :
※ Header/Footer要素の構築に関して:
※ViewModel内にもDataSourceのインスタンスを渡しておく(viewDidLoad時)
① 表示に必要なCellRegistrationの準備
② CellRegistrationとItemTypeを利用したCell生成処理
ViewModelにおけるDataSource要素構築処理の概要
この部分で主に実行するのはDiffableDataSourceの構築と反映となる
① Section用のEnumを定義する(associated valueを用いてHeader・Footerに表示するViewObjectを作成する)
概要をまとめると下記の様な形となる :
② Item用のEnumを定義する(associated valueを用いてCellに表示するViewObjectを作成する)
③ 表示順番に配慮してNSDiffableDataSourceSnapshot<◆◆SectionType,◆◆ItemType>に反映する
// MEMO: 変数currentSnapshotに表示対象のSectionTypeとItemTypeを追加する際のalias
typealias SnapshotElement = (section: [TopSectionType], items: [TopItem])
private var currentSnapshot = NSDiffableDataSourceSnapshot<TopSectionType, TopItem>()
// MEMO: ViewControllerと共有しているDiffableDataSource
private var dataSource: TopViewController.TopDataSource!
※viewDidLoad時にViewControllerから渡されるもの
※DataSourceに追加するSnapshot
Task { @MainActor in
do {
let response = try await self.topResponseUseCase.getResponse()
self.updateTopDataSource(using: response)
} catch let error { // TODO: Error Handling. }
}
例. APIリクエストからDataSourceに加工するまでの流れ
1. 順番に配慮した状態でのAPIレスポンスデータを取得する
2. レスポンスデータを元にしてSnapshotに反映して更新
ViewModel側に定義しているDataSource関連処理(1)
async/awaitを利用したSectionの並び順を担保したResponse取得処理例
概要をまとめると下記の様な形となる :
func getResources() async throws -> [TopResponse] {
var responses: [TopResponse] = []
var endpoints = ["/banner", "/featured”, "/news", "/special", “/photos”]
// エンドポイントの並び順を担保しながらの並列処理を実行する
await withTaskGroup(of: [TopResponse].self, body: { [weak self] group in
guard let self = self else { return }
for endpoint in endpoints {
group.addTask {
// エンドポイントのパス文字列に応じたResponseを取得する処理
return try await APIRequest.shard.get(endpoint: section)
}
}
for await response in group {
responses.append(response)
}
// TODO: Error Handling.
})
return responses
}
RxSwiftを利用する場合は.zipや.flatMap等を活用する。
✨ async/awaitを利用した処理
余談:
protocol TopResponse: Decodable {
var ●●●: String
// …(他に必要なものがあれば定義)…
}
struct TopBannerResponse: TopResponse {
let ●●●: String
// POINT: View表示に必要なデータ格納場所
let content: Content
// TODO: CodingKey設定
}
extension TopBannerResponse {
// POINT: Contentの内容を定義
struct Content: Decodable {
let id: Int
let identifier: String
let imageUrl: URL?
// TODO: CodingKey設定
}
}
Response定義例: 形によっては調整を要する部分
ViewModel側に定義しているDataSource関連処理(2)
並び順を担保したレスポンス情報の配列からSnapshotを作成し画面に反映する
ViewModel側におけるDataSource更新処理の抜粋 :
private func updateTopDataSource(using responses: [TopResponse]) {
// 1. 現在Snapshopをリセットする
currentSnapshot = NSDiffableDataSourceSnapshot<TopSectionType, TopItem>()
// 2. 引数から取得したレスポンスの型を元に分解してSnapshotを生成する
for response in responses {
if let topBannerResponse = response as? TopBannerResponse {
let snapshotElement = getTopBannerSnapshot(topBannerResponse)
appendSnapshotElementInCurrentSnapshot(snapshotElement)
}
…(表示する対象のResponseの分だけSnapshotを生成する処理をする)…
}
// 3. DiffableDataSourceにデータを反映する
dataSource.apply(currentSnapshot, animatingDifferences: true)
}
// メンバ変数: currentSnapshot(反映対象セクションデータの入れ物)に格納する
private func appendSnapshotElementInCurrentSnapshot(_ snapshotElement: SnapshotElement) {
currentSnapshot.appendSections(snapshotElement.section)
currentSnapshot.appendItems(snapshotElement.items, toSection: snapshotElement.section.first!)
}
private func getTopBannerSnapshot(_ topBannerResponse: TopBannerResponse)
-> SnapShotElement? {
// バナーに関するデータの実体がある場所
let content = topBannerResponse.content
…(表示する対象のResponseの分だけSnapshotを生成する処理をする)…
let section = TopSectionType.banner(title: "2022 A/W Selection")
let item = TopItemType.banner(bannerViewObject: TopBannerCell.CellViewObject(
id: content.id, identifier: content.label, imageUrl: content.imageUrl)
)
return SnapShotElement(section: [section], items: [item])
}
① 受け取ったResponseを分解&Section作成
② 反映対象のSnapshot変数への追加
おまけ(1):個人的に気になっていた部分の紹介
UICollectionViewCompositionalLayoutでもDrag&Dropは可能(ただしバグ有り)
記事はこちら: https://briancoyner.github.io/articles/2021-10-12-reorderable-collection-view/
1. 機能の一部としてUICollectionViewを活用
おまけ(2):UICollectionViewで正攻法ではない表現例
積極的に選択はしないがUICollectionViewを利用して構築可能な事例をいくつか
※UICollectionViewLayoutを応用して実現する
2. レイアウト属性部分を自前で1から定義する
旧Safariの様な
動き方をする
横・縦・斜めで
スクロール可能
※UICollectionViewLayoutクラスを継承したもの
今後更に考えていきたい部分について
特にiOS13から利用可能になったUIKitの便利なAPI等の活用
実務の中で改善や新機能のアイデアや試してみたい事はたくさん見つかった様にも感じています。
1. RxSwiftベースで実装している部分を徐々に剥がしてCombineへ置き換え:
RxSwiftでのコードについては私自身もかれこれ4-5年程使ってきて馴染みがある実装である&Combineでは標準搭載されていない
オペレータもあるのでこの部分を見極めながら置き換えていく必要がありそうと感じています。
2. async/awaitでの処理の更なる活用と実践 :
async/awaitの登場によりこれまで複雑になりがちな部分であった部分をシンプルに実装できる可能性には注目しています。(た
だしこの部分は私自身実務内でも経験はあるものの、正直未だに手探り感は否めません)。
3. SwiftUIとUIKitの上手な共存とデザインシステム等とも連携した整理:
業務の中でデザインシステム整備に携わる経験があったので、その際に「SwiftUIの機能でPreviewできると確認しやすいかな」
と感じる事が多くありつつもUIKitがベースになっている場合が多いので他社事例も見ながら考えていきたいです。
まとめ
UICollectionViewを利用した実装はここ数年の進化が目覚ましい部分
1. Section・Itemに対応するEnum定義部分をまずは確認すると良い:
取り扱いRxDataSource・DiffableDataSourceを考えていく場合には、共にSection・Itemに対応するEnum定義の整備が前提ではあ
りますがDiffableDataSourceではHashableへの準拠がポイントになる点があると思います。(特にHash値の重複に注意)
2. Enumのassociated valueを有効活用してCell要素やSupplementaryView要素を上手に構築する:
associated valueにおいてCell要素やSupplementaryView要素に表示する構造体を定義しておき、UICollectionViewに表示する要
素を生成するCellRegistrationやSupplementaryRegistrationとも連動する様にしておくと便利かと思います。
現在ではiOS14以上のバージョンであるならばその便利な機能を活用可能な余地が多いと感じました。
3. 画面実装側での処理とDataSourceの内容構築部分に関する部分を整える:
DataSourceに関する処理については、ViewController側ではCell・SupplementaryView・UICollectionViewCompositionalLayout
の構築処理に専念させて、ViewModelやPresenter層でDataSourceの構築を行う方が良いかと思います。
Thank you for listening !
この資料では感覚的にはイメージできそうだけども、具体的な例がないとわかりにくい部分もあったかもしれません。
改めてUI実装サンプルとも合わせて年内には記事化できる様に進めていければと思います!

More Related Content

PDF
Swift 3 を書くときに知っておきたい API デザインガイドライン #love_swift #akibaswift
PDF
試して感覚を掴んでみるUICollectionViewCompositionalLayout & Combine
PDF
Sansan様 登壇資料
PDF
UICollectionViewLayoutでカバーフローを作りたい!
PDF
少しずつ手厚くして不具合や仕様漏れを防ぐために
PPTX
Deep dive into oss written in swift
PPTX
Deep dive into oss written in swift
PPTX
C# LINQ入門
Swift 3 を書くときに知っておきたい API デザインガイドライン #love_swift #akibaswift
試して感覚を掴んでみるUICollectionViewCompositionalLayout & Combine
Sansan様 登壇資料
UICollectionViewLayoutでカバーフローを作りたい!
少しずつ手厚くして不具合や仕様漏れを防ぐために
Deep dive into oss written in swift
Deep dive into oss written in swift
C# LINQ入門

Similar to RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介 (20)

KEY
形式手法とalloyの紹介
PDF
Xamarin で ReactiveUI を使ってみた
PDF
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
PDF
24時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.1
PDF
Objc05
PDF
C#の新機能勉強会 ~ C#7、8の新機能を活用して速く安全なプログラムを書こう~
PDF
Swiftおさらい
PDF
Xamarin.formsで作成する翻訳機能付きtwitterクライアント
PDF
Swift らしい表現を目指そう #eventdots
PDF
Prism + ReactiveProperty入門
PPTX
個人開発したモバイルアプリを紹介したパワポ資料です。転職活動時にポートフォリオとして使用しました。
PDF
書籍「軽量・高速モバイルデータベース Realm入門」を使って学ぶRealmの勘所
PPTX
BindableProperty 書くのクソダリーんだけど、 あいつなんやねん(仮)
PDF
RxSwiftとMVVMパターンと仲良くなる次のステップ
PDF
WWDC 旅行の余談と Swift Open Hours 3 - Swift ラボで聞いてきた話 #cocoa_kansai
PDF
Refactoring point of Kotlin application
PDF
UITableViewについて
PDF
Uicollectionview
PDF
Livesense tech night immutable-js at a glance
PDF
C#勉強会 ~ C#9の新機能 ~
形式手法とalloyの紹介
Xamarin で ReactiveUI を使ってみた
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
24時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.1
Objc05
C#の新機能勉強会 ~ C#7、8の新機能を活用して速く安全なプログラムを書こう~
Swiftおさらい
Xamarin.formsで作成する翻訳機能付きtwitterクライアント
Swift らしい表現を目指そう #eventdots
Prism + ReactiveProperty入門
個人開発したモバイルアプリを紹介したパワポ資料です。転職活動時にポートフォリオとして使用しました。
書籍「軽量・高速モバイルデータベース Realm入門」を使って学ぶRealmの勘所
BindableProperty 書くのクソダリーんだけど、 あいつなんやねん(仮)
RxSwiftとMVVMパターンと仲良くなる次のステップ
WWDC 旅行の余談と Swift Open Hours 3 - Swift ラボで聞いてきた話 #cocoa_kansai
Refactoring point of Kotlin application
UITableViewについて
Uicollectionview
Livesense tech night immutable-js at a glance
C#勉強会 ~ C#9の新機能 ~
Ad

More from Fumiya Sakai (20)

PDF
iOS側のUIの特徴と見比べるAndroid側でのUI実装のヒント
PDF
Measures for Growth with Firebase Remote Config & Unit Testing Using RxSwift
PDF
2022年の抱負とここ数年続けてきたインプット
PDF
既存プロジェクトで使っていたDIをお引っ越し&DIYすることになった
PDF
動画プレイヤーアプリの開発を通じて学んだ機能を実現するための要点解説
PDF
UI実装に関するセッションを 簡単ながら振り返ってみる(仮)
PDF
最近の業務やAndroid関連のインプットと振り返り
PDF
少しずつキャッチアップしていくAndroidアプリ開発の補足と振り返り
PDF
少しずつキャッチアップしていくAndroidアプリ開発
PDF
UIKitやSwiftUIで表現や動きが特徴的なUI実装事例を考察する
PDF
レイヤー分けをしたアーキテクチャで作るiOSアプリ&バックエンドのサンプル実装をのぞく
PDF
iOSアプリ開発で意識すると役立ちそうな「つなぎ目」の部分について
PDF
デザイナー→Webエンジニア→iOSエンジニアと渡り歩いた僕なりのSwiftとの向き合い方と生かす戦略
PDF
何故に私達(特に私)はアプリのアニメーションや UI表現に魅了されるのか? そして共存と向き合いを考える
PDF
アプリ開発におけるテキスト装飾のアイデア集
PDF
ライブラリやView構造を有効活用して iOSアプリのUIをオシャレにするワザ紹介
PDF
部品に切り分けて考えるView構造とライブラリを上手に活用したUI実装
PDF
UI表現ライブラリを有効活用して iOSアプリのUIをオシャレにするワザ紹介
PDF
iOSアプリで気になった動きや表現を上手にアレンジして活用してみる
PDF
iOSアプリUIとの触れ合いと歩む僕なりのSwiftの楽しみ方
iOS側のUIの特徴と見比べるAndroid側でのUI実装のヒント
Measures for Growth with Firebase Remote Config & Unit Testing Using RxSwift
2022年の抱負とここ数年続けてきたインプット
既存プロジェクトで使っていたDIをお引っ越し&DIYすることになった
動画プレイヤーアプリの開発を通じて学んだ機能を実現するための要点解説
UI実装に関するセッションを 簡単ながら振り返ってみる(仮)
最近の業務やAndroid関連のインプットと振り返り
少しずつキャッチアップしていくAndroidアプリ開発の補足と振り返り
少しずつキャッチアップしていくAndroidアプリ開発
UIKitやSwiftUIで表現や動きが特徴的なUI実装事例を考察する
レイヤー分けをしたアーキテクチャで作るiOSアプリ&バックエンドのサンプル実装をのぞく
iOSアプリ開発で意識すると役立ちそうな「つなぎ目」の部分について
デザイナー→Webエンジニア→iOSエンジニアと渡り歩いた僕なりのSwiftとの向き合い方と生かす戦略
何故に私達(特に私)はアプリのアニメーションや UI表現に魅了されるのか? そして共存と向き合いを考える
アプリ開発におけるテキスト装飾のアイデア集
ライブラリやView構造を有効活用して iOSアプリのUIをオシャレにするワザ紹介
部品に切り分けて考えるView構造とライブラリを上手に活用したUI実装
UI表現ライブラリを有効活用して iOSアプリのUIをオシャレにするワザ紹介
iOSアプリで気になった動きや表現を上手にアレンジして活用してみる
iOSアプリUIとの触れ合いと歩む僕なりのSwiftの楽しみ方
Ad

RxDataSourceをNSDiffableDataSourceへ置き換える際のTips集紹介