Skip to content

Commit

Permalink
Add Coordinator cases
Browse files Browse the repository at this point in the history
  • Loading branch information
antranapp committed Dec 15, 2020
1 parent 753ee3a commit aa0b59e
Show file tree
Hide file tree
Showing 12 changed files with 606 additions and 29 deletions.
24 changes: 24 additions & 0 deletions LeakDetectorDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
7FE0480D25681B29005BE7C7 /* NestedClosuresViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FE0480C25681B29005BE7C7 /* NestedClosuresViewController.swift */; };
7FF11903256736BE000B6C59 /* Closure.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7FF11902256736BE000B6C59 /* Closure.storyboard */; };
7FF1190925673784000B6C59 /* NoLeakNonEscapingClosureViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FF1190825673784000B6C59 /* NoLeakNonEscapingClosureViewController.swift */; };
D62DE9522588B2C200CF5CE1 /* CoordinatorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62DE94E2588B2C200CF5CE1 /* CoordinatorViewController.swift */; };
D62DE9532588B2C200CF5CE1 /* CoordinatorRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62DE94F2588B2C200CF5CE1 /* CoordinatorRootViewController.swift */; };
D62DE9542588B2C200CF5CE1 /* BaseCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62DE9502588B2C200CF5CE1 /* BaseCoordinator.swift */; };
D62DE9552588B2C200CF5CE1 /* Coordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62DE9512588B2C200CF5CE1 /* Coordinator.swift */; };
D640D9DE2563AD7E005ABD34 /* DispatchQueueRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D640D9DD2563AD7E005ABD34 /* DispatchQueueRootViewController.swift */; };
D640D9E42563AE04005ABD34 /* DispatchQueue.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D640D9E32563AE04005ABD34 /* DispatchQueue.storyboard */; };
D640D9EA2563AE60005ABD34 /* NoLeakDispatchAsyncViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D640D9E92563AE60005ABD34 /* NoLeakDispatchAsyncViewController.swift */; };
Expand Down Expand Up @@ -104,6 +108,10 @@
7FE0480C25681B29005BE7C7 /* NestedClosuresViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NestedClosuresViewController.swift; sourceTree = "<group>"; };
7FF11902256736BE000B6C59 /* Closure.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Closure.storyboard; sourceTree = "<group>"; };
7FF1190825673784000B6C59 /* NoLeakNonEscapingClosureViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoLeakNonEscapingClosureViewController.swift; sourceTree = "<group>"; };
D62DE94E2588B2C200CF5CE1 /* CoordinatorViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoordinatorViewController.swift; sourceTree = "<group>"; };
D62DE94F2588B2C200CF5CE1 /* CoordinatorRootViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoordinatorRootViewController.swift; sourceTree = "<group>"; };
D62DE9502588B2C200CF5CE1 /* BaseCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseCoordinator.swift; sourceTree = "<group>"; };
D62DE9512588B2C200CF5CE1 /* Coordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Coordinator.swift; sourceTree = "<group>"; };
D640D9DD2563AD7E005ABD34 /* DispatchQueueRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispatchQueueRootViewController.swift; sourceTree = "<group>"; };
D640D9E32563AE04005ABD34 /* DispatchQueue.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = DispatchQueue.storyboard; sourceTree = "<group>"; };
D640D9E92563AE60005ABD34 /* NoLeakDispatchAsyncViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoLeakDispatchAsyncViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -151,6 +159,7 @@
7F4F1C3A255EE07800A90DA8 /* Leak */ = {
isa = PBXGroup;
children = (
D62DE94D2588B2C200CF5CE1 /* Coordinator */,
7FB179E8257375C000209C04 /* SimpleCases */,
7FB179D4257296FA00209C04 /* LazyVar */,
7FB179C7257225DD00209C04 /* Delegate */,
Expand Down Expand Up @@ -281,6 +290,17 @@
path = NestedClosures;
sourceTree = "<group>";
};
D62DE94D2588B2C200CF5CE1 /* Coordinator */ = {
isa = PBXGroup;
children = (
D62DE94E2588B2C200CF5CE1 /* CoordinatorViewController.swift */,
D62DE94F2588B2C200CF5CE1 /* CoordinatorRootViewController.swift */,
D62DE9502588B2C200CF5CE1 /* BaseCoordinator.swift */,
D62DE9512588B2C200CF5CE1 /* Coordinator.swift */,
);
path = Coordinator;
sourceTree = "<group>";
};
D640D9DC2563AD6C005ABD34 /* DispatchQueue */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -473,11 +493,14 @@
7FB179D62572970800209C04 /* LazyVarRootViewController.swift in Sources */,
7FB179F02573768B00209C04 /* SimpleCasesViewController.swift in Sources */,
7F4F1C40255EE0C700A90DA8 /* CombineViewController.swift in Sources */,
D62DE9542588B2C200CF5CE1 /* BaseCoordinator.swift in Sources */,
7F18D5992565FA730045F6FC /* MainViewController.swift in Sources */,
7FB179E02572971C00209C04 /* LazyVarViewController.swift in Sources */,
D62DE9522588B2C200CF5CE1 /* CoordinatorViewController.swift in Sources */,
7F4F1C712562A78000A90DA8 /* ClosureRootViewController.swift in Sources */,
7FE047EC2567F76C005BE7C7 /* AnimatorViewController.swift in Sources */,
7FB179C9257225F100209C04 /* DelegateRootViewController.swift in Sources */,
D62DE9552588B2C200CF5CE1 /* Coordinator.swift in Sources */,
7FE0480725681A3E005BE7C7 /* NestedClosuresRootViewController.swift in Sources */,
7F4F1C5A25617CBA00A90DA8 /* UIApplication+TopMostController.swift in Sources */,
D640D9EA2563AE60005ABD34 /* NoLeakDispatchAsyncViewController.swift in Sources */,
Expand All @@ -489,6 +512,7 @@
7FBA06D5256A8782000A42C4 /* URLSessionRootViewController.swift in Sources */,
7F18D5912565F4E70045F6FC /* ChildViewController.swift in Sources */,
7F1131782562D8C500438910 /* LeakDetectableViewController.swift in Sources */,
D62DE9532588B2C200CF5CE1 /* CoordinatorRootViewController.swift in Sources */,
7FF1190925673784000B6C59 /* NoLeakNonEscapingClosureViewController.swift in Sources */,
7FBA06F2256B22E2000A42C4 /* FutureViewController.swift in Sources */,
7FE047E82567F6E0005BE7C7 /* AnimateRootViewController.swift in Sources */,
Expand Down
19 changes: 18 additions & 1 deletion LeakDetectorDemo/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,29 @@
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="gcY-qA-I68" style="IBUITableViewCellStyleDefault" id="tPN-E0-m1f">
<rect key="frame" x="0.0" y="593.5" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="tPN-E0-m1f" id="M5Y-Vg-3RY">
<rect key="frame" x="0.0" y="0.0" width="383" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Leak by Coordinator" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="gcY-qA-I68">
<rect key="frame" x="20" y="0.0" width="355" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="No Leak" id="w2m-HG-JUB" userLabel="No Leak">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="mfo-rT-f1S" style="IBUITableViewCellStyleDefault" id="SrQ-Fr-ZSC">
<rect key="frame" x="0.0" y="649.5" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="693" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="SrQ-Fr-ZSC" id="8x2-zc-fwW">
<rect key="frame" x="0.0" y="0.0" width="383" height="43.5"/>
Expand Down
59 changes: 59 additions & 0 deletions LeakDetectorDemo/Leak/Coordinator/BaseCoordinator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// Copyright © 2020 Standard Chartered. All rights reserved.
//

import Combine
import LeakDetector
import UIKit

open class BaseCoordinator<T>: UINavigationController, Coordinator {

public let dependency: T
private var cancellables = Set<AnyCancellable>()

private var trackingViewControllers = WeakSet<UIViewController>()

public init(with dependency: T) {
self.dependency = dependency
super.init(nibName: nil, bundle: nil)
}

@available(*, unavailable)
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

open func start() {}

open func navigate(to destination: Destination, presentInModal: Bool = false, animated: Bool) {
guard let viewController = makeViewController(for: destination) else {
return
}

trackingViewControllers.insert(viewController)

if presentInModal {
present(viewController, animated: animated, completion: nil)
return
}

if viewControllers.isEmpty {
viewControllers = [
viewController,
]
} else {
pushViewController(viewController, animated: animated)
}
}

open func makeViewController(for destination: Destination) -> UIViewController? {
nil
}

deinit {
guard let topViewController = topViewController else {
return
}
LeakDetector.instance.expectDeallocate(objects: trackingViewControllers).sink {}.store(in: &cancellables)
}
}
15 changes: 15 additions & 0 deletions LeakDetectorDemo/Leak/Coordinator/Coordinator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// Copyright © 2020 Standard Chartered. All rights reserved.
//

import UIKit

public protocol Destination {}

public protocol Coordinator: UINavigationController {
associatedtype CoordinatorDependency
var dependency: CoordinatorDependency { get }

func start()
func navigate(to destination: Destination, presentInModal: Bool, animated: Bool)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//
// Copyright © 2020 An Tran. All rights reserved.
//

import Foundation
import UIKit

class CoordinatorRootViewController: LeakDetectableTableViewController {

private enum Scenarios {

enum Leak: String, CaseIterable {
case coordinator1 = "Leak - 1"
}

enum NoLeak: String, CaseIterable {
case coordinator1 = "No Leak - 1"
}
}

override func viewDidLoad() {
super.viewDidLoad()
title = "Coordinator"
}

override func numberOfSections(in tableView: UITableView) -> Int {
2
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0:
return "Leak"
case 1:
return "No Leak"
default:
fatalError("invalid section")
}
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return Scenarios.Leak.allCases.count
case 1:
return Scenarios.NoLeak.allCases.count
default:
fatalError("invalid section")
}
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") ?? UITableViewCell(style: .default, reuseIdentifier: "Cell")

switch indexPath.section {
case 0:
cell.textLabel?.text = Scenarios.Leak.allCases[indexPath.row].rawValue
case 1:
cell.textLabel?.text = Scenarios.NoLeak.allCases[indexPath.row].rawValue
default:
fatalError("invalid section")
}
return cell
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch indexPath.section {
case 0:
let scenario = Scenarios.Leak.allCases[indexPath.row]
switch scenario {
case .coordinator1:
let viewController = CoordinatorViewController()
viewController.title = scenario.rawValue
weakViewController = viewController
navigationController?.pushViewController(viewController, animated: true)
}
case 1:
let scenario = Scenarios.NoLeak.allCases[indexPath.row]
switch scenario {
case .coordinator1:
let viewController = NoLeakDelegateViewController1()
viewController.title = scenario.rawValue
weakViewController = viewController
navigationController?.pushViewController(viewController, animated: true)
}

default:
fatalError("invalid section")
}
}
}
Loading

0 comments on commit aa0b59e

Please sign in to comment.