Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support dynamic tables #42

Merged
merged 19 commits into from
Feb 22, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
68 changes: 68 additions & 0 deletions Example-iOS/ViewControllers/DynamicViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//
// AppearanceViewController.swift
// Example-iOS
//
// Created by Ben on 30/01/2018.
twodayslate marked this conversation as resolved.
Show resolved Hide resolved
// Copyright © 2018 bcylin.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

import UIKit
import QuickTableViewController

internal final class DynamicViewController: QuickTableViewController {

var dynamicRows: [Row] = [] {
didSet {
self.tableView.reloadData()
}
}

override var tableContents: [Section] {
get {
let rows = [
twodayslate marked this conversation as resolved.
Show resolved Hide resolved
TapActionRow(text: "AddCell", action: { _ in
self.dynamicRows.append(
NavigationRow(text: "UITableViewCell", detailText: .subtitle(".subtitle"), action: { _ in })
)
})
] + dynamicRows

twodayslate marked this conversation as resolved.
Show resolved Hide resolved
return [
Section(title: "Tap Action", rows: rows as! [Row & RowStyle])
]
}
set {
twodayslate marked this conversation as resolved.
Show resolved Hide resolved

twodayslate marked this conversation as resolved.
Show resolved Hide resolved
}
}

twodayslate marked this conversation as resolved.
Show resolved Hide resolved
override func viewDidLoad() {
super.viewDidLoad()
title = "Dynamic"

// Register the nib files to the table view for UIAppearance customization (in AppDelegate) to work.
tableView.register(UINib(nibName: "SwitchCell", bundle: .main), forCellReuseIdentifier: "SwitchCell")
tableView.register(UINib(nibName: "TapActionCell", bundle: .main), forCellReuseIdentifier: "TapActionCell")
tableView.register(UINib(nibName: "UITableViewCell", bundle: .main), forCellReuseIdentifier: "UITableViewCell.subtitle")
tableView.register(UINib(nibName: "OptionCell", bundle: .main), forCellReuseIdentifier: "UITableViewCell")
}

}
6 changes: 6 additions & 0 deletions Example-iOS/ViewControllers/RootViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ internal final class RootViewController: QuickTableViewController {
NavigationRow(text: "UILabel customization", detailText: .none, action: { [weak self] _ in
self?.navigationController?.pushViewController(AppearanceViewController(), animated: true)
})
]),

twodayslate marked this conversation as resolved.
Show resolved Hide resolved
Section(title: "Dynamic", rows: [
NavigationRow(text: "Dynamic Rows", detailText: .none, action: { [weak self] _ in
self?.navigationController?.pushViewController(DynamicViewController(), animated: true)
})
])
]
}
Expand Down
14 changes: 14 additions & 0 deletions QuickTableViewController.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@
B5F0FFEA1E9CC6F9007BF1C9 /* SwitchRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F0FFE91E9CC6F9007BF1C9 /* SwitchRow.swift */; };
B5F0FFEC1E9CC72D007BF1C9 /* TapActionRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F0FFEB1E9CC72D007BF1C9 /* TapActionRow.swift */; };
B5F0FFEE1E9CC73D007BF1C9 /* Subtitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F0FFED1E9CC73D007BF1C9 /* Subtitle.swift */; };
F6B15A5423F73E48001DB252 /* QuickTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6B15A5323F73E48001DB252 /* QuickTableView.swift */; };
F6B15A5623F74268001DB252 /* DynamicViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6B15A5523F74268001DB252 /* DynamicViewController.swift */; };
F6B15A5923F745ED001DB252 /* QuickTableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6B15A5723F7458C001DB252 /* QuickTableViewDelegate.swift */; };
F6B15A5A23F745ED001DB252 /* QuickTableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6B15A5723F7458C001DB252 /* QuickTableViewDelegate.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -250,6 +254,9 @@
B5F0FFE91E9CC6F9007BF1C9 /* SwitchRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwitchRow.swift; sourceTree = "<group>"; };
B5F0FFEB1E9CC72D007BF1C9 /* TapActionRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TapActionRow.swift; sourceTree = "<group>"; };
B5F0FFED1E9CC73D007BF1C9 /* Subtitle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Subtitle.swift; sourceTree = "<group>"; };
F6B15A5323F73E48001DB252 /* QuickTableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickTableView.swift; sourceTree = "<group>"; };
F6B15A5523F74268001DB252 /* DynamicViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicViewController.swift; sourceTree = "<group>"; };
F6B15A5723F7458C001DB252 /* QuickTableViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickTableViewDelegate.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -342,6 +349,7 @@
B55475741F2DC3C00027F7C1 /* Configurable.swift */,
B522E1DF1F4AA750004DA5AD /* Reusable.swift */,
B5EC18221B95FD7F0015C665 /* Row.swift */,
F6B15A5723F7458C001DB252 /* QuickTableViewDelegate.swift */,
B5374C8F1FDD7AF700A3EA28 /* RowCompatible.swift */,
B50E73841F2E1BC900481910 /* RowStyle.swift */,
);
Expand Down Expand Up @@ -534,6 +542,7 @@
isa = PBXGroup;
children = (
B5F0FFE51E9CC69C007BF1C9 /* SwitchCell.swift */,
F6B15A5323F73E48001DB252 /* QuickTableView.swift */,
B595627A1B9758BC00D6DAB1 /* TapActionCell.swift */,
);
path = Views;
Expand All @@ -557,6 +566,7 @@
B5A67A1120205F5C0075E0C8 /* CustomizationViewController.swift */,
B51F21A61F417037009BC2C9 /* ExampleViewController.swift */,
B5A67A13202069440075E0C8 /* RootViewController.swift */,
F6B15A5523F74268001DB252 /* DynamicViewController.swift */,
);
path = ViewControllers;
sourceTree = "<group>";
Expand Down Expand Up @@ -1053,6 +1063,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F6B15A5623F74268001DB252 /* DynamicViewController.swift in Sources */,
B51F21A51F417037009BC2C9 /* AppDelegate.swift in Sources */,
B5A37EAE20208EF7009C075F /* AppearanceViewController.swift in Sources */,
B5A67A1220205F5C0075E0C8 /* CustomizationViewController.swift in Sources */,
Expand Down Expand Up @@ -1083,13 +1094,15 @@
B5E619CF1F454CF0005200E1 /* RadioSection.swift in Sources */,
B522E1E01F4AA750004DA5AD /* Reusable.swift in Sources */,
B5EC18231B95FD7F0015C665 /* Row.swift in Sources */,
F6B15A5A23F745ED001DB252 /* QuickTableViewDelegate.swift in Sources */,
B5374C901FDD7AF800A3EA28 /* RowCompatible.swift in Sources */,
B50E73851F2E1BC900481910 /* RowStyle.swift in Sources */,
B5E029211DC7A39200B5C90E /* Section.swift in Sources */,
B5F0FFEE1E9CC73D007BF1C9 /* Subtitle.swift in Sources */,
B5F0FFE61E9CC69C007BF1C9 /* SwitchCell.swift in Sources */,
B5F0FFEA1E9CC6F9007BF1C9 /* SwitchRow.swift in Sources */,
B595627B1B9758BC00D6DAB1 /* TapActionCell.swift in Sources */,
F6B15A5423F73E48001DB252 /* QuickTableView.swift in Sources */,
B5F0FFEC1E9CC72D007BF1C9 /* TapActionRow.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -1135,6 +1148,7 @@
B54A2441208883A300EEBA26 /* Section.swift in Sources */,
B54A2442208883A300EEBA26 /* Subtitle.swift in Sources */,
B54A244C208883A300EEBA26 /* SwitchCell.swift in Sources */,
F6B15A5923F745ED001DB252 /* QuickTableViewDelegate.swift in Sources */,
B54A244A208883A300EEBA26 /* SwitchRow.swift in Sources */,
B54A244D208883A300EEBA26 /* TapActionCell.swift in Sources */,
B54A244B208883A300EEBA26 /* TapActionRow.swift in Sources */,
Expand Down
31 changes: 31 additions & 0 deletions Source/Protocol/QuickTableViewDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// SwitchCell.swift
// QuickTableViewController
//
// Created by Ben on 03/09/2015.
// Copyright (c) 2015 bcylin.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

import Foundation

internal protocol QuickTableViewDelegate {
twodayslate marked this conversation as resolved.
Show resolved Hide resolved
func quickReload()
}
47 changes: 35 additions & 12 deletions Source/QuickTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,17 @@ open class QuickTableViewController: UIViewController, UITableViewDataSource, UI
open var clearsSelectionOnViewWillAppear = true

/// Returns the table view managed by the controller object.
open private(set) var tableView: UITableView = UITableView(frame: .zero, style: .grouped)

open private(set) var tableView: QuickTableView = QuickTableView(frame: .zero, style: .grouped)

twodayslate marked this conversation as resolved.
Show resolved Hide resolved
public private(set) var cachedTableContents: [Section] = []
/// The layout of sections and rows to display in the table view.
open var tableContents: [Section] = [] {
didSet {
tableView.reloadData()
open var tableContents: [Section] {
get {
return self.cachedTableContents
}
set {
self.cachedTableContents = newValue
self.tableView.reloadData()
}
}

Expand All @@ -53,9 +58,19 @@ open class QuickTableViewController: UIViewController, UITableViewDataSource, UI
*/
public convenience init(style: UITableView.Style) {
self.init(nibName: nil, bundle: nil)
tableView = UITableView(frame: .zero, style: style)
tableView = QuickTableView(frame: .zero, style: style)

twodayslate marked this conversation as resolved.
Show resolved Hide resolved
}


twodayslate marked this conversation as resolved.
Show resolved Hide resolved
override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.cachedTableContents = self.tableContents
}

twodayslate marked this conversation as resolved.
Show resolved Hide resolved
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

twodayslate marked this conversation as resolved.
Show resolved Hide resolved
deinit {
tableView.dataSource = nil
tableView.delegate = nil
Expand All @@ -72,6 +87,7 @@ open class QuickTableViewController: UIViewController, UITableViewDataSource, UI
tableView.estimatedRowHeight = 44
tableView.dataSource = self
tableView.delegate = self
tableView.quickDelegate = self
}

open override func viewWillAppear(_ animated: Bool) {
Expand All @@ -84,15 +100,15 @@ open class QuickTableViewController: UIViewController, UITableViewDataSource, UI
// MARK: - UITableViewDataSource

open func numberOfSections(in tableView: UITableView) -> Int {
return tableContents.count
return cachedTableContents.count
}

open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableContents[section].rows.count
return cachedTableContents[section].rows.count
}

open func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return tableContents[section].title
return cachedTableContents[section].title
}

open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
Expand All @@ -112,13 +128,13 @@ open class QuickTableViewController: UIViewController, UITableViewDataSource, UI
}

open func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
return tableContents[section].footer
return cachedTableContents[section].footer
}

// MARK: - UITableViewDelegate

open func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
return tableContents[indexPath.section].rows[indexPath.row].isSelectable
return cachedTableContents[indexPath.section].rows[indexPath.row].isSelectable
}

open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
Expand Down Expand Up @@ -198,3 +214,10 @@ extension QuickTableViewController: SwitchCellDelegate {

}
#endif


extension QuickTableViewController: QuickTableViewDelegate {
internal func quickReload() {
self.cachedTableContents = self.tableContents
}
}
33 changes: 33 additions & 0 deletions Source/Views/QuickTableView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// File.swift
//
//
// Created by Zachary Gorak on 2/14/20.
//

import Foundation
import UIKit

open class QuickTableView: UITableView {
internal var quickDelegate: QuickTableViewDelegate? = nil
twodayslate marked this conversation as resolved.
Show resolved Hide resolved

twodayslate marked this conversation as resolved.
Show resolved Hide resolved
override open func reloadData() {
self.quickDelegate?.quickReload()
super.reloadData()
}

twodayslate marked this conversation as resolved.
Show resolved Hide resolved
override open func reloadSectionIndexTitles() {
self.quickDelegate?.quickReload()
super.reloadSectionIndexTitles()
}

twodayslate marked this conversation as resolved.
Show resolved Hide resolved
override open func reloadSections(_ sections: IndexSet, with animation: UITableView.RowAnimation) {
self.quickDelegate?.quickReload()
super.reloadSections(sections, with: animation)
}

twodayslate marked this conversation as resolved.
Show resolved Hide resolved
override open func reloadRows(at indexPaths: [IndexPath], with animation: UITableView.RowAnimation) {
self.quickDelegate?.quickReload()
super.reloadRows(at: indexPaths, with: animation)
}
}