Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@ options:
minimumXcodeGenVersion: 2.5.0
bundleIdPrefix: com.codecritique
targets:
xkcd:
type: application
platform: iOS
sources:
- sources
- assets
xkcdTests:
type: bundle.unit-test
Tests:
type: bundle.unit-test
platform: iOS
sources:
- xkcdTests
- tests
dependencies:
- target: xkcd
scheme:
testTargets:
- xkcdTests
- Tests
xkcd:
type: application
platform: iOS
sources:
- sources
- assets
postbuildScripts:
- path: scripts/swiftlint.sh
name: SwiftLint
Expand Down
6 changes: 0 additions & 6 deletions sources/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,4 @@ import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?

func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
}
141 changes: 108 additions & 33 deletions sources/ComicDetailsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,29 @@
// Created: 2019-09-21
//


import UIKit

class ComicDetailsViewController: UIViewController {
enum SearchTagSection: CaseIterable {
case onlySection
}

private var tagTableViewDataSource: UITableViewDiffableDataSource<SearchTagSection, Tag>?
private var networkManager = NetworkManager()

var comicId:Int?
var comicImage:UIImage?
var tags:[String]?
var comic: ComicModel?
var comicImage: UIImage?
var tags: [String]?

//Mark: UI Elements
let comicImageView: UIImageView = {
let imageView = UIImageView(frame: CGRect(x: 0,y: 0,width: 150,height: 150))
// MARK: UI Elements
fileprivate let comicImageView: UIImageView = {
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 150, height: 150))
imageView.contentMode = UIView.ContentMode.scaleAspectFill
imageView.clipsToBounds = true
return imageView
}()

let tagCollectionView: UICollectionView = {
fileprivate let tagCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.estimatedItemSize = CGSize(width: 30, height: 30)
Expand All @@ -30,15 +35,15 @@ class ComicDetailsViewController: UIViewController {
return collectionView
}()

let tagTextField: UITextField = {
fileprivate let tagTextField: UITextField = {
let tagTextField = UITextField(frame: CGRect.zero)
tagTextField.translatesAutoresizingMaskIntoConstraints = false
tagTextField.borderStyle = .roundedRect
tagTextField.backgroundColor = .white
return tagTextField
}()

let addTagButton: UIButton = {
fileprivate let addTagButton: UIButton = {
let addTagButton = UIButton(frame: CGRect.zero)
addTagButton.setTitle("Add", for: .normal)
addTagButton.contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
Expand All @@ -47,21 +52,43 @@ class ComicDetailsViewController: UIViewController {
return addTagButton
}()

//Mark: Methods
fileprivate var searchTagTableView: UITableView = {
let tableView = UITableView(frame: CGRect.zero)
tableView.translatesAutoresizingMaskIntoConstraints = false
return tableView
}()

// MARK: Methods
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white

title = comicId.map { String($0) } ?? "Unknown"
comicImageView.image = comicImage
if let title = comic?.id {
self.title = String(title)
} else {
title = "unknown"
}

loadTags()
setupNavigationBar()
layoutElements()
setupTagCollectionView()
setUpSearchTagTableView()

networkManager.fetchTags { [weak self] (result) in
switch result {
case .success(let tags):
let snapShot = NSDiffableDataSourceSnapshot<SearchTagSection, Tag>()
snapShot.appendSections([SearchTagSection.onlySection])
snapShot.appendItems(tags)
self?.tagTableViewDataSource?.apply(snapShot)
case .failure(let error):
print("Error: ", error)
}
}
}

fileprivate static func createHorizontalRowStack() -> UIStackView{
fileprivate static func createHorizontalRowStack() -> UIStackView {
let horizontalStackView = UIStackView(frame: CGRect.zero)
horizontalStackView.axis = .horizontal
horizontalStackView.translatesAutoresizingMaskIntoConstraints = false
Expand All @@ -74,13 +101,13 @@ class ComicDetailsViewController: UIViewController {
fileprivate static func createColumnStack() -> UIStackView {
let verticalStackView = UIStackView(frame: CGRect.zero)
verticalStackView.axis = .vertical
verticalStackView.translatesAutoresizingMaskIntoConstraints = false;
verticalStackView.translatesAutoresizingMaskIntoConstraints = false
return verticalStackView
}

fileprivate func layoutElements() {

let stackContainer = ComicDetailsViewController.createColumnStack()
stackContainer.distribution = .fill
let topRow = ComicDetailsViewController.createHorizontalRowStack()
let middleRow = ComicDetailsViewController.createHorizontalRowStack()

Expand All @@ -93,6 +120,7 @@ class ComicDetailsViewController: UIViewController {
//Establish layout hierarchy
stackContainer.addArrangedSubview(topRow)
stackContainer.addArrangedSubview(middleRow)
stackContainer.addArrangedSubview(searchTagTableView)
view.addSubview(stackContainer)

//Add the constraints
Expand All @@ -101,33 +129,66 @@ class ComicDetailsViewController: UIViewController {
tagTextField.heightAnchor.constraint(equalToConstant: 30).isActive = true
addTagButton.heightAnchor.constraint(equalToConstant: 30).isActive = true

searchTagTableView.widthAnchor.constraint(equalTo: stackContainer.widthAnchor).isActive = true

stackContainer.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
stackContainer.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
stackContainer.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
stackContainer.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
}

fileprivate func setupNavigationBar() {
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(onCancel))
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(onSave))
navigationItem.leftBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .cancel,
target: self,
action: #selector(onCancel)
)
navigationItem.rightBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .save,
target: self,
action: #selector(onSave)
)
navigationController?.navigationBar.isTranslucent = false
}

fileprivate func setUpSearchTagTableView() {
searchTagTableView.register(TagTableViewCell.self, forCellReuseIdentifier: "TagTableViewCell")
self.tagTableViewDataSource = makeTagTableViewDataSource()
searchTagTableView.dataSource = tagTableViewDataSource
searchTagTableView.delegate = self
}

private func makeTagTableViewDataSource() -> UITableViewDiffableDataSource<SearchTagSection, Tag> {
return UITableViewDiffableDataSource(
tableView: searchTagTableView) { (tableView, indexPath, tag) -> UITableViewCell? in
let cell = tableView.dequeueReusableCell(
withIdentifier: "TagTableViewCell",
for: indexPath
)

cell.textLabel?.text = tag.title
return cell
}
}

fileprivate func setupTagCollectionView() {
tagCollectionView.register(TagCell.self, forCellWithReuseIdentifier: "TagCell")
tagCollectionView.register(TagCollectionViewCell.self, forCellWithReuseIdentifier: "TagCell")
tagCollectionView.dataSource = self
tagCollectionView.delegate = self
}

fileprivate func loadTags() {
tags = ["Astronomy", "Discovery", "Futility", "Survival", "Scientist"].sorted()
tags = ["Astronomy", "Discovery", "Futility", "Survival", "Scientist"].sorted()
}

//Mark: Navigation Actions
@objc func onSave() {
//To do callback
// MARK: Navigation Actions
@objc
fileprivate func onSave() {
//Todo callback
}

@objc func onCancel() {
@objc
fileprivate func onCancel() {
dismiss(animated: true)
}
}
Expand All @@ -138,23 +199,32 @@ extension ComicDetailsViewController: UICollectionViewDataSource {
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let tagCell = collectionView.dequeueReusableCell(withReuseIdentifier: "TagCell", for: indexPath) as? TagCell else {
guard let tagCell = collectionView.dequeueReusableCell(
withReuseIdentifier: "TagCell",
for: indexPath
) as? TagCollectionViewCell else {
return UICollectionViewCell()
}
tagCell.textLabel.text = tags?[indexPath.row]
return tagCell
}

}

extension ComicDetailsViewController: UICollectionViewDelegate {

}

extension ComicDetailsViewController: UITableViewDelegate {

class TagCell: UICollectionViewCell {
}

class TagTableViewCell: UITableViewCell {

}

var textLabel:UILabel = {
class TagCollectionViewCell: UICollectionViewCell {

fileprivate var textLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.font = UIFont.preferredFont(forTextStyle: .subheadline)
Expand All @@ -163,7 +233,17 @@ class TagCell: UICollectionViewCell {

override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}

private func commonInit() {
addSubview(textLabel)

textLabel.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
textLabel.heightAnchor.constraint(equalTo: self.heightAnchor).isActive = true
self.widthAnchor.constraint(equalTo: textLabel.widthAnchor, constant: 8).isActive = true
Expand All @@ -172,11 +252,6 @@ class TagCell: UICollectionViewCell {
layer.cornerRadius = 8.0
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
print("Not implemented")
}

override var isSelected: Bool {
didSet {
switch isSelected {
Expand Down
Loading