SlideShare ist ein Scribd-Unternehmen logo
1 von 83
Downloaden Sie, um offline zu lesen










📦










class TimelineTableViewController: UITableViewController {
private var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
@IBOutlet weak var emptyView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
TwitterManager.getTimeline() { [weak self] timeline in
self?.timeline = timeline
self?.showEmptyViewIfNeeded(timeline)
}
}
private func showEmptyViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems == 0 {
emptyView.isHidden = false
} else {
emptyView.isHidden = true
}
}
}








class TimelineTableViewController: UITableViewController {
private var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
@IBOutlet weak var emptyView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
TwitterManager.getTimeline() { [weak self] timeline in
self?.timeline = timeline
self?.showEmptyViewIfNeeded(timeline)
}
}
private func showEmptyViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems == 0 {
emptyView.isHidden = false
} else {
emptyView.isHidden = true
}
}
}




👃
class TimelineTableViewController: UITableViewController {
private var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
@IBOutlet weak var emptyView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
TwitterManager.getTimeline() { [weak self] timeline in
self?.timeline = timeline
self?.showEmptyViewIfNeeded(timeline)
}
}
private func showEmptyViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems == 0 {
emptyView.isHidden = false
} else {
emptyView.isHidden = true
}
}
}


class TimelineTableViewController: UITableViewController {
private var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
@IBOutlet weak var emptyView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
TwitterManager.getTimeline() { [weak self] timeline in
self?.timeline = timeline
self?.showEmptyViewIfNeeded(timeline)
}
}
private func showEmptyViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems == 0 {
emptyView.isHidden = false
} else {
emptyView.isHidden = true
}
}
}


💢😡
☺










class TimelineTableViewController: UITableViewController {
private var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
@IBOutlet weak var emptyView: UIView!
@IBOutlet weak var adView: AdView!
override func viewDidLoad() {
super.viewDidLoad()
TwitterManager.getTimeline() { [weak self] timeline in
self?.timeline = timeline
self?.showEmptyViewIfNeeded(timeline)
self?.showAdViewIfNeeded(timeline)
}
}
private func showEmptyViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems == 0 {
emptyView.isHidden = false
} else {
emptyView.isHidden = true
}
}
private func showAdViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 {
adView.isHidden = false
} else {
adView.isHidden = true
}
}
}






class TimelineTableViewController: UITableViewController {
private var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
@IBOutlet weak var emptyView: UIView!
@IBOutlet weak var adView: AdView!
@IBOutlet weak var loginView: LoginView!
private var isLogined = false
override func viewDidLoad() {
super.viewDidLoad()
LoginManager.login() { [weak self] isSucceed in
if isSucceed {
self?.isLogined = true
TwitterManager.getTimeline() { [weak self] timeline in
self?.timeline = timeline
self?.showEmptyViewIfNeeded(timeline)
self?.showAdViewIfNeeded(timeline)
}
} else {
self?.isLogined = false
}
self?.showLoginViewIfNeeded()
}
}
private func showEmptyViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems == 0 {
emptyView.isHidden = false
} else {
emptyView.isHidden = true
}
}
private func showAdViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 {
adView.isHidden = false
} else {
adView.isHidden = true
}
}
private func showLoginViewIfNeeded() {
if isLogined {
loginView.isHidden = true
} else {
loginView.isHidden = false
}
}
}
class TimelineTableViewController: UITableViewController {
private var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
@IBOutlet weak var emptyView: UIView!
@IBOutlet weak var adView: AdView!
@IBOutlet weak var loginView: LoginView!
private var isLogined = false
override func viewDidLoad() {
super.viewDidLoad()
LoginManager.login() { [weak self] isSucceed in
guard let `self` = self else { return }
if isSucceed {
TwitterManager.getTimeline() { [weak self] timeline in
guard let `self` = self else { return }
self.timeline = timeline
self.showEmptyViewIfNeeded(timeline)
self.showAdViewIfNeeded(timeline)
self.showLoginViewIfNeeded()
}
}
}
}
private func showEmptyViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems == 0 {
emptyView.isHidden = false
} else {
emptyView.isHidden = true
}
}
private func showAdViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 {
adView.isHidden = false
} else {
adView.isHidden = true
}
}
private func showLoginViewIfNeeded() {
if isLogined {
loginView.isHidden = true
} else {
loginView.isHidden = false
}
}
private var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
@IBOutlet weak var emptyView: UIView!
@IBOutlet weak var adView: AdView!
@IBOutlet weak var loginView: LoginView!
private var isLogined = false
override func viewDidLoad() {
super.viewDidLoad()
}
}
class TimelineTableViewController: UITableViewController {
private var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
@IBOutlet weak var emptyView: UIView!
@IBOutlet weak var adView: AdView!
@IBOutlet weak var loginView: LoginView!
private var isLogined = false
override func viewDidLoad() {
super.viewDidLoad()
LoginManager.login() { [weak self] isSucceed in
guard let `self` = self else { return }
if isSucceed {
TwitterManager.getTimeline() { [weak self] timeline in
guard let `self` = self else { return }
self.timeline = timeline
self.showEmptyViewIfNeeded(timeline)
self.showAdViewIfNeeded(timeline)
self.showLoginViewIfNeeded()
}
}
}
}
private func showEmptyViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems == 0 {
emptyView.isHidden = false
} else {
emptyView.isHidden = true
}
}
private func showAdViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 {
adView.isHidden = false
} else {
adView.isHidden = true
}
}
private func showLoginViewIfNeeded() {
if isLogined {
loginView.isHidden = true
} else {
loginView.isHidden = false
}
}
private var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
@IBOutlet weak var emptyView: UIView!
@IBOutlet weak var adView: AdView!
@IBOutlet weak var loginView: LoginView!
private var isLogined = false
override func viewDidLoad() {
super.viewDidLoad()
LoginManager.login() { [weak self] isSucceed in
guard let `self` = self else { return }
if isSucceed {
TwitterManager.getTimeline() { [weak self] timeline in
guard let `self` = self else { return }
self.timeline = timeline
self.showEmptyViewIfNeeded(timeline)
self.showAdViewIfNeeded(timeline)
self.showLoginViewIfNeeded()
}
}
}
}
}
class TimelineTableViewController: UITableViewController {
private var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
@IBOutlet weak var emptyView: UIView!
@IBOutlet weak var adView: AdView!
@IBOutlet weak var loginView: LoginView!
private var isLogined = false
override func viewDidLoad() {
super.viewDidLoad()
LoginManager.login() { [weak self] isSucceed in
guard let `self` = self else { return }
if isSucceed {
TwitterManager.getTimeline() { [weak self] timeline in
guard let `self` = self else { return }
self.timeline = timeline
self.showEmptyViewIfNeeded(timeline)
self.showAdViewIfNeeded(timeline)
self.showLoginViewIfNeeded()
}
}
}
}
private func showEmptyViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems == 0 {
emptyView.isHidden = false
} else {
emptyView.isHidden = true
}
}
private func showAdViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 {
adView.isHidden = false
} else {
adView.isHidden = true
}
}
private func showLoginViewIfNeeded() {
if isLogined {
loginView.isHidden = true
} else {
loginView.isHidden = false
}
}
private var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
@IBOutlet weak var emptyView: UIView!
@IBOutlet weak var adView: AdView!
@IBOutlet weak var loginView: LoginView!
private var isLogined = false
override func viewDidLoad() {
super.viewDidLoad()
LoginManager.login() { [weak self] isSucceed in
guard let `self` = self else { return }
if isSucceed {
TwitterManager.getTimeline() { [weak self] timeline in
guard let `self` = self else { return }
self.timeline = timeline
self.showEmptyViewIfNeeded(timeline)
self.showAdViewIfNeeded(timeline)
self.showLoginViewIfNeeded()
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
LoginManager.login() { [weak self] isSucceed in
guard let `self` = self else { return }
if isSucceed {
TwitterManager.getTimeline() { [weak self] timeline in
guard let `self` = self else { return }
self.timeline = timeline
self.showEmptyViewIfNeeded(timeline)
self.showAdViewIfNeeded(timeline)
self.showLoginViewIfNeeded()
}
}
}
}
}










💡




😄




🙌
🤔
😡👊💢






































protocol TimelineTableVCOutput: class {
func showEmptyView()
func hideEmptyView()
func showTimeline(timeline: Timeline)
}
class TimelineTableViewController: UITableViewController {
@IBOutlet weak var emptyView: UIView!
// Presenter
private var timelinePresenter: TimelinePresenter!
fileprivate var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Presenter
timelinePresenter = TimelinePresenter(output: self)
}
@IBAction func tapGetTimelineButton(_ sender: Any) {
// Presenter
timelinePresenter?.getTimeline()
}
}




class TimelineTableViewController: UITableViewController {
@IBOutlet weak var emptyView: UIView!
// Presenter
private var timelinePresenter: TimelinePresenter!
fileprivate var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Presenter
timelinePresenter = TimelinePresenter(output: self)
}
@IBAction func tapGetTimelineButton(_ sender: Any) {
// Presenter
timelinePresenter?.getTimeline()
}
}




class TimelineTableViewController: UITableViewController {
@IBOutlet weak var emptyView: UIView!
// Presenter
private var timelinePresenter: TimelinePresenter!
fileprivate var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Presenter
timelinePresenter = TimelinePresenter(output: self)
}
@IBAction func tapGetTimelineButton(_ sender: Any) {
// Presenter
timelinePresenter?.getTimeline()
}
}
extension TimelineViewController: TimelineTableVCOutput {
func showEmptyView() {
emptyView.isHidden = false
}
func hideEmptyView() {
emptyView.isHidden = true
}
func showTimeline(timeline: Timeline) {
self.timeline = timeline
}
}
class TimelinePresenter {
private weak var timelineTableVCOutput: TimelineTableVCOutput!
private var timelineUseCase = TimelineUseCase()
init(output timelineTableVCOutput: TimelineTableVCOutput) {
self.timelineTableVCOutput = timelineTableVCOutput
}
func getTimeline() {
timelineUseCase.getTimeline() { [weak self] result in
switch result {
case .failure:
self?.timelineViewControllerDelegate.showEmptyView()
case .success(let timeline):
self?.timelineViewControllerDelegate.hideEmptyView()
self?.timelineViewControllerDelegate.showTimeline(timeline: timeline)
}
}
}
}
class TimelinePresenter {
private weak var timelineTableVCOutput: TimelineTableVCOutput!
private var timelineUseCase = TimelineUseCase()
init(output timelineTableVCOutput: TimelineTableVCOutput) {
self.timelineTableVCOutput = timelineTableVCOutput
}
func getTimeline() {
timelineUseCase.getTimeline() { [weak self] result in
switch result {
case .failure:
self?.timelineTableVCOutput.showEmptyView()
case .success(let timeline):
self?.timelineTableVCOutput.hideEmptyView()
self?.timelineTableVCOutput.showTimeline(timeline: timeline)
}
}
}
}


















protocol TimelineTableVCOutput: class {
func showEmptyView()
func hideEmptyView()
func showAdView()
func hideAdView()
func showTimeline(timeline: Timeline)
}
class TimelineTableViewController: UITableViewController {
@IBOutlet weak var emptyView: UIView!
@IBOutlet weak var adView: AdView!
// Presenter
private var timelinePresenter: TimelinePresenter!
fileprivate var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Presenter
timelinePresenter = TimelinePresenter(output: self)
}
@IBAction func tapGetTimelineButton(_ sender: Any) {
// Presenter
timelinePresenter?.getTimeline()
}
}






















extension TimelineTableViewController: TimelineTableVCOutput {
func showEmptyView() {
emptyView.isHidden = false
}
func hideEmptyView() {
emptyView.isHidden = true
}
func showAdView() {
adView.isHidden = false
}
func hideAdView() {
adView.isHidden = true
}
func showTimeline(timeline: Timeline) {
self.timeline = timeline
}
}
class TimelinePresenter {
private weak var timelineTableVCOutput: TimelineTableVCOutput!
private var timelineUseCase = TimelineUseCase()
init(output timelineTableVCOutput: TimelineTableVCOutput) {
self.timelineTableVCOutput = timelineTableVCOutput
}
func getTimeline() {
timelineUseCase.getTimeline() { [weak self] result in
switch result {
case .failure:
self?.timelineTableVCOutput.showEmptyView()
self?.timelineTableVCOutput.hideAdView()
case .success(let timeline):
self?.timelineTableVCOutput.hideEmptyView()
self?.timelineTableVCOutput.showTimeline(timeline: timeline)
self?.showAdViewIfNeeded(timeline: timeline)
}
}
}
private func showAdViewIfNeeded(timeline: Timeline) {
if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 {
timelineTableVCOutput.showAdView()
} else {
timelineTableVCOutput.hideAdView()
}
}
}
















class TimelineTableViewController: UITableViewController {
private var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
@IBOutlet weak var emptyView: UIView!
@IBOutlet weak var adView: AdView!
override func viewDidLoad() {
super.viewDidLoad()
TwitterManager.getTimeline() { [weak self] timeline in
self?.timeline = timeline
self?.showEmptyViewIfNeeded(timeline)
self?.showAdViewIfNeeded(timeline)
}
}
private func showEmptyViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems == 0 {
emptyView.isHidden = false
} else {
emptyView.isHidden = true
}
}
private func showAdViewIfNeeded(_ timeline: Timeline) {
if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 {
adView.isHidden = false
} else {
adView.isHidden = true
}
}
}








class TimelineTableViewController: UITableViewController {
@IBOutlet weak var emptyView: UIView!
@IBOutlet weak var adView: AdView!
// Presenter
private var timelinePresenter: TimelinePresenter!
fileprivate var timeline: Timeline? = nil {
didSet {
tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Presenter
timelinePresenter = TimelinePresenter(output: self)
}
@IBAction func tapGetTimelineButton(_ sender: Any) {
// Presenter
timelinePresenter?.getTimeline()
}
}
extension TimelineTableViewController: TimelineTableVCOutput {
func showEmptyView() {
emptyView.isHidden = false
}
func hideEmptyView() {
emptyView.isHidden = true
}
func showAdView() {
adView.isHidden = false
}
func hideAdView() {
adView.isHidden = true
}
func showTimeline(timeline: Timeline) {
self.timeline = timeline
}
}




class TimelinePresenter {
private weak var timelineTableVCOutput: TimelineTableVCOutput!
private var timelineUseCase = TimelineUseCase()
init(output timelineTableVCOutput: TimelineTableVCOutput) {
self.timelineTableVCOutput = timelineTableVCOutput
}
func getTimeline() {
timelineUseCase.getTimeline() { [weak self] result in
switch result {
case .failure:
self?.timelineTableVCOutput.showEmptyView()
self?.timelineTableVCOutput.hideAdView()
case .success(let timeline):
self?.timelineTableVCOutput.hideEmptyView()
self?.timelineTableVCOutput.showTimeline(timeline: timeline)
self?.showAdViewIfNeeded(timeline: timeline)
}
}
}
private func showAdViewIfNeeded(timeline: Timeline) {
if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 {
timelineTableVCOutput.showAdView()
} else {
timelineTableVCOutput.hideAdView()
}
}
}


👋
























VC「もしかして...」Model「私たち...」「「入れ替わってるー!?」」を前前前世から防ぐ方法
VC「もしかして...」Model「私たち...」「「入れ替わってるー!?」」を前前前世から防ぐ方法
VC「もしかして...」Model「私たち...」「「入れ替わってるー!?」」を前前前世から防ぐ方法

Weitere ähnliche Inhalte

Was ist angesagt?

Awesome State Management for React and Other Virtual-Dom Libraries
Awesome State Management for React and Other Virtual-Dom LibrariesAwesome State Management for React and Other Virtual-Dom Libraries
Awesome State Management for React and Other Virtual-Dom Libraries
FITC
 
Get started with YUI
Get started with YUIGet started with YUI
Get started with YUI
Adam Lu
 

Was ist angesagt? (19)

Awesome State Management for React and Other Virtual-Dom Libraries
Awesome State Management for React and Other Virtual-Dom LibrariesAwesome State Management for React and Other Virtual-Dom Libraries
Awesome State Management for React and Other Virtual-Dom Libraries
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Chaincode Development 區塊鏈鏈碼開發
Chaincode Development 區塊鏈鏈碼開發Chaincode Development 區塊鏈鏈碼開發
Chaincode Development 區塊鏈鏈碼開發
 
Get started with YUI
Get started with YUIGet started with YUI
Get started with YUI
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web services
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
 
Sylius and Api Platform The story of integration
Sylius and Api Platform The story of integrationSylius and Api Platform The story of integration
Sylius and Api Platform The story of integration
 
Backbone - TDC 2011 Floripa
Backbone - TDC 2011 FloripaBackbone - TDC 2011 Floripa
Backbone - TDC 2011 Floripa
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testing
 
Event sourcing w PHP (by Piotr Kacała)
Event sourcing w PHP (by Piotr Kacała)Event sourcing w PHP (by Piotr Kacała)
Event sourcing w PHP (by Piotr Kacała)
 
Ruby - Design patterns tdc2011
Ruby - Design patterns tdc2011Ruby - Design patterns tdc2011
Ruby - Design patterns tdc2011
 
Django quickstart
Django quickstartDjango quickstart
Django quickstart
 
Symfony World - Symfony components and design patterns
Symfony World - Symfony components and design patternsSymfony World - Symfony components and design patterns
Symfony World - Symfony components and design patterns
 
Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.
 
Reactive, component 그리고 angular2
Reactive, component 그리고  angular2Reactive, component 그리고  angular2
Reactive, component 그리고 angular2
 
A short tale about state machine
A short tale about state machineA short tale about state machine
A short tale about state machine
 
Epic South Disasters
Epic South DisastersEpic South Disasters
Epic South Disasters
 
RxSwift 활용하기 - Let'Swift 2017
RxSwift 활용하기 - Let'Swift 2017RxSwift 활용하기 - Let'Swift 2017
RxSwift 활용하기 - Let'Swift 2017
 
LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기
 

Ähnlich wie VC「もしかして...」Model「私たち...」「「入れ替わってるー!?」」を前前前世から防ぐ方法

Ähnlich wie VC「もしかして...」Model「私たち...」「「入れ替わってるー!?」」を前前前世から防ぐ方法 (20)

Swift Delhi: Practical POP
Swift Delhi: Practical POPSwift Delhi: Practical POP
Swift Delhi: Practical POP
 
Practical Protocol-Oriented-Programming
Practical Protocol-Oriented-ProgrammingPractical Protocol-Oriented-Programming
Practical Protocol-Oriented-Programming
 
Practialpop 160510130818
Practialpop 160510130818Practialpop 160510130818
Practialpop 160510130818
 
MCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in Swift
MCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in SwiftMCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in Swift
MCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in Swift
 
描画とビジネスをクリーンに分ける Osaka 公開用
描画とビジネスをクリーンに分ける Osaka 公開用描画とビジネスをクリーンに分ける Osaka 公開用
描画とビジネスをクリーンに分ける Osaka 公開用
 
Smooth scrolling in UITableView and UICollectionView
Smooth scrolling in UITableView and UICollectionViewSmooth scrolling in UITableView and UICollectionView
Smooth scrolling in UITableView and UICollectionView
 
Optimize CollectionView Scrolling
Optimize CollectionView ScrollingOptimize CollectionView Scrolling
Optimize CollectionView Scrolling
 
Daniel Jalkut - dotSwift 2019
Daniel Jalkut - dotSwift 2019Daniel Jalkut - dotSwift 2019
Daniel Jalkut - dotSwift 2019
 
View controller life cycle
View controller life cycleView controller life cycle
View controller life cycle
 
Vue-3-Cheat-Sheet.pdf
Vue-3-Cheat-Sheet.pdfVue-3-Cheat-Sheet.pdf
Vue-3-Cheat-Sheet.pdf
 
Beautiful java script
Beautiful java scriptBeautiful java script
Beautiful java script
 
RxBinding-kotlin
RxBinding-kotlinRxBinding-kotlin
RxBinding-kotlin
 
20180721 code defragment
20180721 code defragment20180721 code defragment
20180721 code defragment
 
Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022
Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022
Does testability imply good design - Andrzej Jóźwiak - TomTom Dev Day 2022
 
Intro programacion funcional
Intro programacion funcionalIntro programacion funcional
Intro programacion funcional
 
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV) Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
 
Building complex User Interfaces with Sitecore and React
Building complex User Interfaces with Sitecore and ReactBuilding complex User Interfaces with Sitecore and React
Building complex User Interfaces with Sitecore and React
 
Writing Your App Swiftly
Writing Your App SwiftlyWriting Your App Swiftly
Writing Your App Swiftly
 
Tinkerbelles return home from their Guinness world-record attempt on Sunday
Tinkerbelles return home from their Guinness world-record attempt on SundayTinkerbelles return home from their Guinness world-record attempt on Sunday
Tinkerbelles return home from their Guinness world-record attempt on Sunday
 
NongBeer MVP Demo application
NongBeer MVP Demo applicationNongBeer MVP Demo application
NongBeer MVP Demo application
 

Mehr von Kenji Tanaka

リリース前のリグレッションテストがめんどい!のでMagic PodでUIテストを試してみる #pixiv_app_night
リリース前のリグレッションテストがめんどい!のでMagic PodでUIテストを試してみる #pixiv_app_nightリリース前のリグレッションテストがめんどい!のでMagic PodでUIテストを試してみる #pixiv_app_night
リリース前のリグレッションテストがめんどい!のでMagic PodでUIテストを試してみる #pixiv_app_night
Kenji Tanaka
 

Mehr von Kenji Tanaka (20)

FatViewControllerを安全に書き換える方法が見つからなかったので、どういう痛みを許容するか考えた #iosdc
FatViewControllerを安全に書き換える方法が見つからなかったので、どういう痛みを許容するか考えた #iosdcFatViewControllerを安全に書き換える方法が見つからなかったので、どういう痛みを許容するか考えた #iosdc
FatViewControllerを安全に書き換える方法が見つからなかったので、どういう痛みを許容するか考えた #iosdc
 
リリース前のリグレッションテストがめんどい!のでMagic PodでUIテストを試してみる #pixiv_app_night
リリース前のリグレッションテストがめんどい!のでMagic PodでUIテストを試してみる #pixiv_app_nightリリース前のリグレッションテストがめんどい!のでMagic PodでUIテストを試してみる #pixiv_app_night
リリース前のリグレッションテストがめんどい!のでMagic PodでUIテストを試してみる #pixiv_app_night
 
ポストモーテムやってみた #yjbonfire
ポストモーテムやってみた #yjbonfireポストモーテムやってみた #yjbonfire
ポストモーテムやってみた #yjbonfire
 
2つの同期 4つの状態 #pixiv_ios_arch
2つの同期 4つの状態 #pixiv_ios_arch2つの同期 4つの状態 #pixiv_ios_arch
2つの同期 4つの状態 #pixiv_ios_arch
 
2つの同期 4つの状態 #app_mp
2つの同期 4つの状態 #app_mp2つの同期 4つの状態 #app_mp
2つの同期 4つの状態 #app_mp
 
2つの同期 4つの状態 #roppongiswift
2つの同期 4つの状態 #roppongiswift2つの同期 4つの状態 #roppongiswift
2つの同期 4つの状態 #roppongiswift
 
トークンリフレッシュ処理を含むAPIClientのテスト #hakata_test_night
トークンリフレッシュ処理を含むAPIClientのテスト #hakata_test_nightトークンリフレッシュ処理を含むAPIClientのテスト #hakata_test_night
トークンリフレッシュ処理を含むAPIClientのテスト #hakata_test_night
 
よく使うテストヘルパーの紹介 #ios_test_night
よく使うテストヘルパーの紹介 #ios_test_nightよく使うテストヘルパーの紹介 #ios_test_night
よく使うテストヘルパーの紹介 #ios_test_night
 
Swiftで聞いておぼえるテスト書き
Swiftで聞いておぼえるテスト書きSwiftで聞いておぼえるテスト書き
Swiftで聞いておぼえるテスト書き
 
設計時空のリファクタリング
設計時空のリファクタリング設計時空のリファクタリング
設計時空のリファクタリング
 
WACATE 2018 Summer
WACATE 2018 SummerWACATE 2018 Summer
WACATE 2018 Summer
 
テスト駆動開発入門 by Swift
テスト駆動開発入門 by Swiftテスト駆動開発入門 by Swift
テスト駆動開発入門 by Swift
 
An iOS Engineer challenges Web.
An iOS Engineer challenges Web.An iOS Engineer challenges Web.
An iOS Engineer challenges Web.
 
エンジニアのためのブログ講座Ver4
エンジニアのためのブログ講座Ver4エンジニアのためのブログ講座Ver4
エンジニアのためのブログ講座Ver4
 
TDDやってみよ
TDDやってみよTDDやってみよ
TDDやってみよ
 
ストレス社会に生きる、iOSエンジニアにオススメする百合の世界と作品
ストレス社会に生きる、iOSエンジニアにオススメする百合の世界と作品ストレス社会に生きる、iOSエンジニアにオススメする百合の世界と作品
ストレス社会に生きる、iOSエンジニアにオススメする百合の世界と作品
 
iOS 11からのDeviceCheck #とは
iOS 11からのDeviceCheck #とはiOS 11からのDeviceCheck #とは
iOS 11からのDeviceCheck #とは
 
設計に答えはないから探してみよう
設計に答えはないから探してみよう設計に答えはないから探してみよう
設計に答えはないから探してみよう
 
iOS 11からのアプリ間ファイル共有
iOS 11からのアプリ間ファイル共有iOS 11からのアプリ間ファイル共有
iOS 11からのアプリ間ファイル共有
 
iOS 11からのアプリ間ファイル共有_公開用
iOS 11からのアプリ間ファイル共有_公開用iOS 11からのアプリ間ファイル共有_公開用
iOS 11からのアプリ間ファイル共有_公開用
 

Kürzlich hochgeladen

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Kürzlich hochgeladen (20)

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 

VC「もしかして...」Model「私たち...」「「入れ替わってるー!?」」を前前前世から防ぐ方法

  • 3.
  • 4.
  • 5.
  • 6.
  • 8.
  • 9.
  • 10.
  • 11. class TimelineTableViewController: UITableViewController { private var timeline: Timeline? = nil { didSet { tableView.reloadData() } } @IBOutlet weak var emptyView: UIView! override func viewDidLoad() { super.viewDidLoad() TwitterManager.getTimeline() { [weak self] timeline in self?.timeline = timeline self?.showEmptyViewIfNeeded(timeline) } } private func showEmptyViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems == 0 { emptyView.isHidden = false } else { emptyView.isHidden = true } } } 
 

  • 12. 
 
 class TimelineTableViewController: UITableViewController { private var timeline: Timeline? = nil { didSet { tableView.reloadData() } } @IBOutlet weak var emptyView: UIView! override func viewDidLoad() { super.viewDidLoad() TwitterManager.getTimeline() { [weak self] timeline in self?.timeline = timeline self?.showEmptyViewIfNeeded(timeline) } } private func showEmptyViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems == 0 { emptyView.isHidden = false } else { emptyView.isHidden = true } } }
  • 13.
  • 14.
  • 15.
  • 17. class TimelineTableViewController: UITableViewController { private var timeline: Timeline? = nil { didSet { tableView.reloadData() } } @IBOutlet weak var emptyView: UIView! override func viewDidLoad() { super.viewDidLoad() TwitterManager.getTimeline() { [weak self] timeline in self?.timeline = timeline self?.showEmptyViewIfNeeded(timeline) } } private func showEmptyViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems == 0 { emptyView.isHidden = false } else { emptyView.isHidden = true } } } 

  • 18. class TimelineTableViewController: UITableViewController { private var timeline: Timeline? = nil { didSet { tableView.reloadData() } } @IBOutlet weak var emptyView: UIView! override func viewDidLoad() { super.viewDidLoad() TwitterManager.getTimeline() { [weak self] timeline in self?.timeline = timeline self?.showEmptyViewIfNeeded(timeline) } } private func showEmptyViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems == 0 { emptyView.isHidden = false } else { emptyView.isHidden = true } } }
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26. 
 
 
 class TimelineTableViewController: UITableViewController { private var timeline: Timeline? = nil { didSet { tableView.reloadData() } } @IBOutlet weak var emptyView: UIView! @IBOutlet weak var adView: AdView! override func viewDidLoad() { super.viewDidLoad() TwitterManager.getTimeline() { [weak self] timeline in self?.timeline = timeline self?.showEmptyViewIfNeeded(timeline) self?.showAdViewIfNeeded(timeline) } } private func showEmptyViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems == 0 { emptyView.isHidden = false } else { emptyView.isHidden = true } } private func showAdViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 { adView.isHidden = false } else { adView.isHidden = true } } }
  • 27. 
 
 
 class TimelineTableViewController: UITableViewController { private var timeline: Timeline? = nil { didSet { tableView.reloadData() } } @IBOutlet weak var emptyView: UIView! @IBOutlet weak var adView: AdView! @IBOutlet weak var loginView: LoginView! private var isLogined = false override func viewDidLoad() { super.viewDidLoad() LoginManager.login() { [weak self] isSucceed in if isSucceed { self?.isLogined = true TwitterManager.getTimeline() { [weak self] timeline in self?.timeline = timeline self?.showEmptyViewIfNeeded(timeline) self?.showAdViewIfNeeded(timeline) } } else { self?.isLogined = false } self?.showLoginViewIfNeeded() } } private func showEmptyViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems == 0 { emptyView.isHidden = false } else { emptyView.isHidden = true } } private func showAdViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 { adView.isHidden = false } else { adView.isHidden = true } } private func showLoginViewIfNeeded() { if isLogined { loginView.isHidden = true } else { loginView.isHidden = false } } }
  • 28. class TimelineTableViewController: UITableViewController { private var timeline: Timeline? = nil { didSet { tableView.reloadData() } } @IBOutlet weak var emptyView: UIView! @IBOutlet weak var adView: AdView! @IBOutlet weak var loginView: LoginView! private var isLogined = false override func viewDidLoad() { super.viewDidLoad() LoginManager.login() { [weak self] isSucceed in guard let `self` = self else { return } if isSucceed { TwitterManager.getTimeline() { [weak self] timeline in guard let `self` = self else { return } self.timeline = timeline self.showEmptyViewIfNeeded(timeline) self.showAdViewIfNeeded(timeline) self.showLoginViewIfNeeded() } } } } private func showEmptyViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems == 0 { emptyView.isHidden = false } else { emptyView.isHidden = true } } private func showAdViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 { adView.isHidden = false } else { adView.isHidden = true } } private func showLoginViewIfNeeded() { if isLogined { loginView.isHidden = true } else { loginView.isHidden = false } } private var timeline: Timeline? = nil { didSet { tableView.reloadData() } } @IBOutlet weak var emptyView: UIView! @IBOutlet weak var adView: AdView! @IBOutlet weak var loginView: LoginView! private var isLogined = false override func viewDidLoad() { super.viewDidLoad() } }
  • 29. class TimelineTableViewController: UITableViewController { private var timeline: Timeline? = nil { didSet { tableView.reloadData() } } @IBOutlet weak var emptyView: UIView! @IBOutlet weak var adView: AdView! @IBOutlet weak var loginView: LoginView! private var isLogined = false override func viewDidLoad() { super.viewDidLoad() LoginManager.login() { [weak self] isSucceed in guard let `self` = self else { return } if isSucceed { TwitterManager.getTimeline() { [weak self] timeline in guard let `self` = self else { return } self.timeline = timeline self.showEmptyViewIfNeeded(timeline) self.showAdViewIfNeeded(timeline) self.showLoginViewIfNeeded() } } } } private func showEmptyViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems == 0 { emptyView.isHidden = false } else { emptyView.isHidden = true } } private func showAdViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 { adView.isHidden = false } else { adView.isHidden = true } } private func showLoginViewIfNeeded() { if isLogined { loginView.isHidden = true } else { loginView.isHidden = false } } private var timeline: Timeline? = nil { didSet { tableView.reloadData() } } @IBOutlet weak var emptyView: UIView! @IBOutlet weak var adView: AdView! @IBOutlet weak var loginView: LoginView! private var isLogined = false override func viewDidLoad() { super.viewDidLoad() LoginManager.login() { [weak self] isSucceed in guard let `self` = self else { return } if isSucceed { TwitterManager.getTimeline() { [weak self] timeline in guard let `self` = self else { return } self.timeline = timeline self.showEmptyViewIfNeeded(timeline) self.showAdViewIfNeeded(timeline) self.showLoginViewIfNeeded() } } } } }
  • 30. class TimelineTableViewController: UITableViewController { private var timeline: Timeline? = nil { didSet { tableView.reloadData() } } @IBOutlet weak var emptyView: UIView! @IBOutlet weak var adView: AdView! @IBOutlet weak var loginView: LoginView! private var isLogined = false override func viewDidLoad() { super.viewDidLoad() LoginManager.login() { [weak self] isSucceed in guard let `self` = self else { return } if isSucceed { TwitterManager.getTimeline() { [weak self] timeline in guard let `self` = self else { return } self.timeline = timeline self.showEmptyViewIfNeeded(timeline) self.showAdViewIfNeeded(timeline) self.showLoginViewIfNeeded() } } } } private func showEmptyViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems == 0 { emptyView.isHidden = false } else { emptyView.isHidden = true } } private func showAdViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 { adView.isHidden = false } else { adView.isHidden = true } } private func showLoginViewIfNeeded() { if isLogined { loginView.isHidden = true } else { loginView.isHidden = false } } private var timeline: Timeline? = nil { didSet { tableView.reloadData() } } @IBOutlet weak var emptyView: UIView! @IBOutlet weak var adView: AdView! @IBOutlet weak var loginView: LoginView! private var isLogined = false override func viewDidLoad() { super.viewDidLoad() LoginManager.login() { [weak self] isSucceed in guard let `self` = self else { return } if isSucceed { TwitterManager.getTimeline() { [weak self] timeline in guard let `self` = self else { return } self.timeline = timeline self.showEmptyViewIfNeeded(timeline) self.showAdViewIfNeeded(timeline) self.showLoginViewIfNeeded() } } } } override func viewDidLoad() { super.viewDidLoad() LoginManager.login() { [weak self] isSucceed in guard let `self` = self else { return } if isSucceed { TwitterManager.getTimeline() { [weak self] timeline in guard let `self` = self else { return } self.timeline = timeline self.showEmptyViewIfNeeded(timeline) self.showAdViewIfNeeded(timeline) self.showLoginViewIfNeeded() } } } } }
  • 31.
  • 32.
  • 33.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42. 😄
  • 44. 🙌
  • 45. 🤔
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 56. 
 
 
 
 
 
 
 
 
 protocol TimelineTableVCOutput: class { func showEmptyView() func hideEmptyView() func showTimeline(timeline: Timeline) }
  • 57. class TimelineTableViewController: UITableViewController { @IBOutlet weak var emptyView: UIView! // Presenter private var timelinePresenter: TimelinePresenter! fileprivate var timeline: Timeline? = nil { didSet { tableView.reloadData() } } override func viewDidLoad() { super.viewDidLoad() // Presenter timelinePresenter = TimelinePresenter(output: self) } @IBAction func tapGetTimelineButton(_ sender: Any) { // Presenter timelinePresenter?.getTimeline() } } 

  • 58. 
 class TimelineTableViewController: UITableViewController { @IBOutlet weak var emptyView: UIView! // Presenter private var timelinePresenter: TimelinePresenter! fileprivate var timeline: Timeline? = nil { didSet { tableView.reloadData() } } override func viewDidLoad() { super.viewDidLoad() // Presenter timelinePresenter = TimelinePresenter(output: self) } @IBAction func tapGetTimelineButton(_ sender: Any) { // Presenter timelinePresenter?.getTimeline() } }
  • 59. 
 
 class TimelineTableViewController: UITableViewController { @IBOutlet weak var emptyView: UIView! // Presenter private var timelinePresenter: TimelinePresenter! fileprivate var timeline: Timeline? = nil { didSet { tableView.reloadData() } } override func viewDidLoad() { super.viewDidLoad() // Presenter timelinePresenter = TimelinePresenter(output: self) } @IBAction func tapGetTimelineButton(_ sender: Any) { // Presenter timelinePresenter?.getTimeline() } }
  • 60. extension TimelineViewController: TimelineTableVCOutput { func showEmptyView() { emptyView.isHidden = false } func hideEmptyView() { emptyView.isHidden = true } func showTimeline(timeline: Timeline) { self.timeline = timeline } }
  • 61. class TimelinePresenter { private weak var timelineTableVCOutput: TimelineTableVCOutput! private var timelineUseCase = TimelineUseCase() init(output timelineTableVCOutput: TimelineTableVCOutput) { self.timelineTableVCOutput = timelineTableVCOutput } func getTimeline() { timelineUseCase.getTimeline() { [weak self] result in switch result { case .failure: self?.timelineViewControllerDelegate.showEmptyView() case .success(let timeline): self?.timelineViewControllerDelegate.hideEmptyView() self?.timelineViewControllerDelegate.showTimeline(timeline: timeline) } } } }
  • 62. class TimelinePresenter { private weak var timelineTableVCOutput: TimelineTableVCOutput! private var timelineUseCase = TimelineUseCase() init(output timelineTableVCOutput: TimelineTableVCOutput) { self.timelineTableVCOutput = timelineTableVCOutput } func getTimeline() { timelineUseCase.getTimeline() { [weak self] result in switch result { case .failure: self?.timelineTableVCOutput.showEmptyView() case .success(let timeline): self?.timelineTableVCOutput.hideEmptyView() self?.timelineTableVCOutput.showTimeline(timeline: timeline) } } } }
  • 64. 
 
 
 
 
 
 
 protocol TimelineTableVCOutput: class { func showEmptyView() func hideEmptyView() func showAdView() func hideAdView() func showTimeline(timeline: Timeline) }
  • 65. class TimelineTableViewController: UITableViewController { @IBOutlet weak var emptyView: UIView! @IBOutlet weak var adView: AdView! // Presenter private var timelinePresenter: TimelinePresenter! fileprivate var timeline: Timeline? = nil { didSet { tableView.reloadData() } } override func viewDidLoad() { super.viewDidLoad() // Presenter timelinePresenter = TimelinePresenter(output: self) } @IBAction func tapGetTimelineButton(_ sender: Any) { // Presenter timelinePresenter?.getTimeline() } } 
 
 
 
 

  • 66. 
 
 
 
 
 
 extension TimelineTableViewController: TimelineTableVCOutput { func showEmptyView() { emptyView.isHidden = false } func hideEmptyView() { emptyView.isHidden = true } func showAdView() { adView.isHidden = false } func hideAdView() { adView.isHidden = true } func showTimeline(timeline: Timeline) { self.timeline = timeline } }
  • 67. class TimelinePresenter { private weak var timelineTableVCOutput: TimelineTableVCOutput! private var timelineUseCase = TimelineUseCase() init(output timelineTableVCOutput: TimelineTableVCOutput) { self.timelineTableVCOutput = timelineTableVCOutput } func getTimeline() { timelineUseCase.getTimeline() { [weak self] result in switch result { case .failure: self?.timelineTableVCOutput.showEmptyView() self?.timelineTableVCOutput.hideAdView() case .success(let timeline): self?.timelineTableVCOutput.hideEmptyView() self?.timelineTableVCOutput.showTimeline(timeline: timeline) self?.showAdViewIfNeeded(timeline: timeline) } } } private func showAdViewIfNeeded(timeline: Timeline) { if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 { timelineTableVCOutput.showAdView() } else { timelineTableVCOutput.hideAdView() } } } 
 
 
 
 

  • 68.
  • 69. 
 
 
 class TimelineTableViewController: UITableViewController { private var timeline: Timeline? = nil { didSet { tableView.reloadData() } } @IBOutlet weak var emptyView: UIView! @IBOutlet weak var adView: AdView! override func viewDidLoad() { super.viewDidLoad() TwitterManager.getTimeline() { [weak self] timeline in self?.timeline = timeline self?.showEmptyViewIfNeeded(timeline) self?.showAdViewIfNeeded(timeline) } } private func showEmptyViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems == 0 { emptyView.isHidden = false } else { emptyView.isHidden = true } } private func showAdViewIfNeeded(_ timeline: Timeline) { if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 { adView.isHidden = false } else { adView.isHidden = true } } }
  • 70. 
 
 
 
 class TimelineTableViewController: UITableViewController { @IBOutlet weak var emptyView: UIView! @IBOutlet weak var adView: AdView! // Presenter private var timelinePresenter: TimelinePresenter! fileprivate var timeline: Timeline? = nil { didSet { tableView.reloadData() } } override func viewDidLoad() { super.viewDidLoad() // Presenter timelinePresenter = TimelinePresenter(output: self) } @IBAction func tapGetTimelineButton(_ sender: Any) { // Presenter timelinePresenter?.getTimeline() } }
  • 71. extension TimelineTableViewController: TimelineTableVCOutput { func showEmptyView() { emptyView.isHidden = false } func hideEmptyView() { emptyView.isHidden = true } func showAdView() { adView.isHidden = false } func hideAdView() { adView.isHidden = true } func showTimeline(timeline: Timeline) { self.timeline = timeline } }
  • 72. 
 
 class TimelinePresenter { private weak var timelineTableVCOutput: TimelineTableVCOutput! private var timelineUseCase = TimelineUseCase() init(output timelineTableVCOutput: TimelineTableVCOutput) { self.timelineTableVCOutput = timelineTableVCOutput } func getTimeline() { timelineUseCase.getTimeline() { [weak self] result in switch result { case .failure: self?.timelineTableVCOutput.showEmptyView() self?.timelineTableVCOutput.hideAdView() case .success(let timeline): self?.timelineTableVCOutput.hideEmptyView() self?.timelineTableVCOutput.showTimeline(timeline: timeline) self?.showAdViewIfNeeded(timeline: timeline) } } } private func showAdViewIfNeeded(timeline: Timeline) { if timeline?.numberOfItems >= 1 && timeline?.numberOfItems <= 3 { timelineTableVCOutput.showAdView() } else { timelineTableVCOutput.hideAdView() } } }
  • 73.
  • 74. 👋
  • 76.
  • 77.
  • 78.