SlideShare a Scribd company logo
1 of 40
AbemaTV iOS社内ランチ勉強会 2018/04/10
Yuji Hato
5分で学ぶ
差分更新とRxDataSources
About me
Yuji Hato
CyberAgent, Inc. / AbemaTV, Inc.
dekatotoro
@dekatotoro
Contributed services
RxDataSources
RxDataSources
RxDataSources って何?
RxDataSources
RxSwiftのためのUITableViewと
UICollectionViewのDataSource
RxDataSources
何が嬉しいの?
RxDataSources
UITableView,
UICollectionViewの
delete, insert, move
が簡単に実装できる !
RxDataSources
delete, insert, moveのための更新の差分
を抽出するアルゴリズムは正確にやろうとす
るとけっこう難しい… 🙄
RxDataSources
差分抽出アルゴリズム
RxDataSources
・Wagner-Fischer
・Heckel
・Myers
・Wu
…
RxDataSources
差分抽出アルゴリズムのライブラリ
RxDataSources
・osteslag/Changeset … Wagner-Fischer
・jflinter/Dwifft … Myers
・wokalski/Diff.swift … Myers
・onyarnold/Differ … Myers(Diff.swiftのfork)
・onmyway133/DeepDiff … Heckelぽい
・Instagram/IGListKit … Heckel
・RxSwiftCommunity/RxDataSources
… Heckel改
・kazuhiro4949/EditDistance … Wu
RxDataSources
IGListKit … Sectionを表現した多次元
配列の差分には対応していない
RxDataSources … ユニークIDを持ち、
配列に重複がない前提でSectionの差分更
新
RxDataSources
↓ これわかりやすい
https://github.com/horita-
yuya/DifferenceAlgorithmCompariso
n
RxDataSources
実装
RxDataSources
RxDataSources
SectionModelのprotocol
public protocol SectionModelType {
associatedtype Item
public var items: [Self.Item] { get }
public init(original: Self, items: [Self.Item])
}
RxDataSources
public protocol IdentifiableType {
associatedtype Identity : Hashable
public var identity: Self.Identity { get }
}
RxDataSources
public protocol AnimatableSectionModelType : SectionModelType, IdentifiableType where
Self.Item : IdentifiableType, Self.Item : Equatable {
}
RxDataSources
RxDataSources
SectionModel
enum DownloadSeriesSectionModel: AnimatableSectionModelType {
typealias Item = DownloadSeriesSectionItem
case episodeList(season: DownloadSeason?, items: [Item])
case other(items: [Item])
// Mark: - IdentifiableType
var identity: String {
…
}
// Mark: - SectionModelType
var items: [DownloadSeriesSectionItem] {
switch self {
case .episodeList(_, let items):
return items
case .other(let items):
return items
}
}
init(original: DownloadSeriesSectionModel, items: [Item]) {
switch original {
case .episodeList(let season, _):
self = .episodeList(season: season, items: items)
case .other:
self = .other(items: items)
}
}
}
RxDataSources
RxDataSources
SectionItemModel
enum DownloadSeriesSectionItem: IdentifiableType, Equatable {
case episode(downloadMedia: DownloadMedia)
case seeOtherEpisode(series: DownloadSeries)
// Mark: - IdentifiableType
var identity: String {
…
}
// Mark: - Equatable
static func == (lhs: DownloadSeriesSectionItem, rhs: DownloadSeriesSectionItem) -> Bool {
…
}
}
RxDataSources
RxDataSources
AnimatableSectionModel
public struct AnimatableSectionModel<Section: IdentifiableType, ItemType: IdentifiableType & Equatable> {
public var model: Section
public var items: [Item]
public init(model: Section, items: [ItemType]) {
self.model = model
self.items = items
}
}
extension AnimatableSectionModel
: AnimatableSectionModelType {
public typealias Item = ItemType
public typealias Identity = Section.Identity
public var identity: Section.Identity {
return model.identity
}
public init(original: AnimatableSectionModel, items: [Item]) {
self.model = original.model
self.items = items
}
public var hashValue: Int {
return self.model.identity.hashValue
}
}
RxDataSources
よく見たら
RxDataSourcesに
AnimatableSectionMod
elが用意されているの
でこれを使うのがbetter
RxDataSources
RxTableViewSectionedAnimatedDataSource
open class RxTableViewSectionedAnimatedDataSource<S: AnimatableSectionModelType>
: TableViewSectionedDataSource<S>
, RxTableViewDataSourceType {
…
public init(
animationConfiguration: AnimationConfiguration = AnimationConfiguration(),
decideViewTransition: @escaping DecideViewTransition = { _, _, _ in .animated },
configureCell: @escaping ConfigureCell,
titleForHeaderInSection: @escaping TitleForHeaderInSection = { _, _ in nil },
titleForFooterInSection: @escaping TitleForFooterInSection = { _, _ in nil },
canEditRowAtIndexPath: @escaping CanEditRowAtIndexPath = { _, _ in false },
canMoveRowAtIndexPath: @escaping CanMoveRowAtIndexPath = { _, _ in false },
sectionIndexTitles: @escaping SectionIndexTitles = { _ in nil },
sectionForSectionIndexTitle: @escaping SectionForSectionIndexTitle = { _, _, index in index }
) {
self.animationConfiguration = animationConfiguration
self.decideViewTransition = decideViewTransition
super.init(
configureCell: configureCell,
titleForHeaderInSection: titleForHeaderInSection,
titleForFooterInSection: titleForFooterInSection,
canEditRowAtIndexPath: canEditRowAtIndexPath,
canMoveRowAtIndexPath: canMoveRowAtIndexPath,
sectionIndexTitles: sectionIndexTitles,
sectionForSectionIndexTitle: sectionForSectionIndexTitle
)
}
…
}
RxDataSources
final class DownloadSeriesDelegate: NSObject, UITableViewDelegate {
…
lazy var dataSource: RxTableViewSectionedAnimatedDataSource<DownloadSeriesSectionModel> = .init(
animationConfiguration: AnimationConfiguration(insertAnimation: .fade,
reloadAnimation: .none,
deleteAnimation: .fade),
configureCell: { [weak self] dataSource, table, indexPath, item in
guard let me = self else {
return UITableViewCell() // Should never reach here.
}
switch item {
case .episode(let downloadMedia):
let cell = table.dequeueReusableCell(DownloadListMediaCell.self, forIndexPath: indexPath)
cell.configure(downloadMedia: downloadMedia)
…
return cell
case .seeOtherEpisode(let series):
let cell = table.dequeueReusableCell(DownloadSeeOtherEpisodeCell.self, forIndexPath: indexPath)
cell.rx.tapGesture
.subscribe(onNext: { [weak self] in
…
})
.disposed(by: cell.reusableDisposeBag)
…
return cell
}
})
…
RxDataSources
final class DownloadSeriesViewStream {
…
let sectionModels: Property<[DownloadSeriesSectionModel]>
private let _sectionModels = Variable<[DownloadSeriesSectionModel]>([])
…
}
RxDataSources
final class DownloadSeriesViewController: UIViewController {
…
viewStream.sectionModels.asObservable()
// IMPORTANT:
// crash回避、要調査.
.throttle(1.0, latest: true, scheduler: ConcurrentMainScheduler.instance)
.bind(to: tableView.rx.items(dataSource: delegate.dataSource))
.disposed(by: rx.disposeBag)
…
RxDataSources
RxDataSources
UITableViewDelegateは?
// MARK: - UITableViewDelegate
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
…
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
…
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
…
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
…
}
…
RxDataSources
AbemaTVにおけるRxDataSourcesの歴史
AbemaTVにおけるRxDataSourcesの歴史
ジャンルトップの無料絞込のために追加
2017/09/11
AbemaTVにおけるRxDataSourcesの歴史
廃止 !?
2017/11/07
AbemaTVにおけるRxDataSourcesの歴史
ダウンロードリストのために追加
2018/02/08
Conclusion
Conclusion
• 差分抽出アルゴリズムのライブラリも検討しよ
う
• Diffアルゴリズムは自前で作ろうとするとけっこう大変
• RxSwift使っているならRxDataSourcesで良さそ
う
Thank you

More Related Content

What's hot

オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
Yoji Kanno
 

What's hot (20)

Rest ful api設計入門
Rest ful api設計入門Rest ful api設計入門
Rest ful api設計入門
 
SPAのルーティングの話
SPAのルーティングの話SPAのルーティングの話
SPAのルーティングの話
 
こわくない Git
こわくない Gitこわくない Git
こわくない Git
 
世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture
 
ドメイン駆動設計のための Spring の上手な使い方
ドメイン駆動設計のための Spring の上手な使い方ドメイン駆動設計のための Spring の上手な使い方
ドメイン駆動設計のための Spring の上手な使い方
 
会社でClojure使ってみて分かったこと
会社でClojure使ってみて分かったこと会社でClojure使ってみて分かったこと
会社でClojure使ってみて分かったこと
 
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
 
このIRのグラフがすごい!上場企業2020
このIRのグラフがすごい!上場企業2020このIRのグラフがすごい!上場企業2020
このIRのグラフがすごい!上場企業2020
 
Marp Tutorial
Marp TutorialMarp Tutorial
Marp Tutorial
 
Laravelの認証について
Laravelの認証についてLaravelの認証について
Laravelの認証について
 
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
 
ドメイン駆動設計 失敗したことと成功したこと
ドメイン駆動設計 失敗したことと成功したことドメイン駆動設計 失敗したことと成功したこと
ドメイン駆動設計 失敗したことと成功したこと
 
Dockerfileを改善するためのBest Practice 2019年版
Dockerfileを改善するためのBest Practice 2019年版Dockerfileを改善するためのBest Practice 2019年版
Dockerfileを改善するためのBest Practice 2019年版
 
【Unity道場】ゲーム制作に使う数学を学習しよう
【Unity道場】ゲーム制作に使う数学を学習しよう【Unity道場】ゲーム制作に使う数学を学習しよう
【Unity道場】ゲーム制作に使う数学を学習しよう
 
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
 
go generate 完全入門
go generate 完全入門go generate 完全入門
go generate 完全入門
 
Spring Boot × Vue.jsでSPAを作る
Spring Boot × Vue.jsでSPAを作るSpring Boot × Vue.jsでSPAを作る
Spring Boot × Vue.jsでSPAを作る
 
ドライブレコーダの画像認識による道路情報の自動差分抽出
ドライブレコーダの画像認識による道路情報の自動差分抽出ドライブレコーダの画像認識による道路情報の自動差分抽出
ドライブレコーダの画像認識による道路情報の自動差分抽出
 
絶対に描いてはいけないグラフ入りスライド24枚
絶対に描いてはいけないグラフ入りスライド24枚絶対に描いてはいけないグラフ入りスライド24枚
絶対に描いてはいけないグラフ入りスライド24枚
 
コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!
 

Similar to 5分で学ぶ差分更新とRxDataSources

Adaptive UI - 解像度の異なるデバイスや画面の向きに対応する 最適なレイアウトへ -
Adaptive UI  - 解像度の異なるデバイスや画面の向きに対応する 最適なレイアウトへ - Adaptive UI  - 解像度の異なるデバイスや画面の向きに対応する 最適なレイアウトへ -
Adaptive UI - 解像度の異なるデバイスや画面の向きに対応する 最適なレイアウトへ -
Yuji Hato
 
Entity Attribute Value (Eav)
Entity   Attribute   Value (Eav)Entity   Attribute   Value (Eav)
Entity Attribute Value (Eav)
Tâm
 
Running Intelligent Applications inside a Database: Deep Learning with Python...
Running Intelligent Applications inside a Database: Deep Learning with Python...Running Intelligent Applications inside a Database: Deep Learning with Python...
Running Intelligent Applications inside a Database: Deep Learning with Python...
Miguel González-Fierro
 

Similar to 5分で学ぶ差分更新とRxDataSources (20)

Compass Framework
Compass FrameworkCompass Framework
Compass Framework
 
Adaptive UI - 解像度の異なるデバイスや画面の向きに対応する 最適なレイアウトへ -
Adaptive UI  - 解像度の異なるデバイスや画面の向きに対応する 最適なレイアウトへ - Adaptive UI  - 解像度の異なるデバイスや画面の向きに対応する 最適なレイアウトへ -
Adaptive UI - 解像度の異なるデバイスや画面の向きに対応する 最適なレイアウトへ -
 
前端MVC之BackboneJS
前端MVC之BackboneJS前端MVC之BackboneJS
前端MVC之BackboneJS
 
Entity Attribute Value (Eav)
Entity   Attribute   Value (Eav)Entity   Attribute   Value (Eav)
Entity Attribute Value (Eav)
 
Magento Indexes
Magento IndexesMagento Indexes
Magento Indexes
 
Questioning the status quo
Questioning the status quoQuestioning the status quo
Questioning the status quo
 
Integrating SAP the Java EE Way - JBoss One Day talk 2012
Integrating SAP the Java EE Way - JBoss One Day talk 2012Integrating SAP the Java EE Way - JBoss One Day talk 2012
Integrating SAP the Java EE Way - JBoss One Day talk 2012
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
SADI in Perl - Protege Plugin Tutorial (fixed Aug 24, 2011)
SADI in Perl - Protege Plugin Tutorial (fixed Aug 24, 2011)SADI in Perl - Protege Plugin Tutorial (fixed Aug 24, 2011)
SADI in Perl - Protege Plugin Tutorial (fixed Aug 24, 2011)
 
droidparts
droidpartsdroidparts
droidparts
 
JavaOne 2017 - JNoSQL: The Definitive Solution for Java and NoSQL Database [C...
JavaOne 2017 - JNoSQL: The Definitive Solution for Java and NoSQL Database [C...JavaOne 2017 - JNoSQL: The Definitive Solution for Java and NoSQL Database [C...
JavaOne 2017 - JNoSQL: The Definitive Solution for Java and NoSQL Database [C...
 
Relevance trilogy may dream be with you! (dec17)
Relevance trilogy  may dream be with you! (dec17)Relevance trilogy  may dream be with you! (dec17)
Relevance trilogy may dream be with you! (dec17)
 
Data visualization in python/Django
Data visualization in python/DjangoData visualization in python/Django
Data visualization in python/Django
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
Deep dive into Oracle ADF
Deep dive into Oracle ADFDeep dive into Oracle ADF
Deep dive into Oracle ADF
 
Java and xml
Java and xmlJava and xml
Java and xml
 
CCM AlchemyAPI and Real-time Aggregation
CCM AlchemyAPI and Real-time AggregationCCM AlchemyAPI and Real-time Aggregation
CCM AlchemyAPI and Real-time Aggregation
 
What Lies Beneath
What Lies BeneathWhat Lies Beneath
What Lies Beneath
 
Demystifying The Solid Works Api
Demystifying The Solid Works ApiDemystifying The Solid Works Api
Demystifying The Solid Works Api
 
Running Intelligent Applications inside a Database: Deep Learning with Python...
Running Intelligent Applications inside a Database: Deep Learning with Python...Running Intelligent Applications inside a Database: Deep Learning with Python...
Running Intelligent Applications inside a Database: Deep Learning with Python...
 

More from Yuji Hato (8)

継続的な開発スタイル 「AbemaTV iOSアプリを週一でリリースしている話」
継続的な開発スタイル 「AbemaTV iOSアプリを週一でリリースしている話」継続的な開発スタイル 「AbemaTV iOSアプリを週一でリリースしている話」
継続的な開発スタイル 「AbemaTV iOSアプリを週一でリリースしている話」
 
iOSDC 2018 動画をなめらかに動かす技術
iOSDC 2018 動画をなめらかに動かす技術iOSDC 2018 動画をなめらかに動かす技術
iOSDC 2018 動画をなめらかに動かす技術
 
AbemaTV モバイルアプリの開発体制と開発プロセスの話
AbemaTV モバイルアプリの開発体制と開発プロセスの話AbemaTV モバイルアプリの開発体制と開発プロセスの話
AbemaTV モバイルアプリの開発体制と開発プロセスの話
 
Apple TV tvOS入門 Iosdc2017
Apple TV tvOS入門 Iosdc2017Apple TV tvOS入門 Iosdc2017
Apple TV tvOS入門 Iosdc2017
 
AbemaTV on tvOS
AbemaTV on tvOSAbemaTV on tvOS
AbemaTV on tvOS
 
Flux with RxSwift
Flux with RxSwiftFlux with RxSwift
Flux with RxSwift
 
CarPlayの対応方法と日本での現状
CarPlayの対応方法と日本での現状CarPlayの対応方法と日本での現状
CarPlayの対応方法と日本での現状
 
AWA with Realm
AWA with RealmAWA with Realm
AWA with Realm
 

Recently uploaded

CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
anilsa9823
 

Recently uploaded (20)

The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 

5分で学ぶ差分更新とRxDataSources

Editor's Notes

  1. コードの例です