diff --git a/The Plate Game.xcodeproj/project.pbxproj b/The Plate Game.xcodeproj/project.pbxproj index 273ebea..12566f4 100644 --- a/The Plate Game.xcodeproj/project.pbxproj +++ b/The Plate Game.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 706FBAA71DB446E300B7F984 /* AppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 706FBAA61DB446E300B7F984 /* AppCoordinator.swift */; }; + 709EF18D1E1F22A70095FE96 /* Region.swift in Sources */ = {isa = PBXBuildFile; fileRef = 709EF18C1E1F22A70095FE96 /* Region.swift */; }; 70C4A47F1DA6FC160037FF8C /* PersistenceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70C4A47E1DA6FC160037FF8C /* PersistenceManager.swift */; }; 70C4A4811DA701F80037FF8C /* RegionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70C4A4801DA701F80037FF8C /* RegionManager.swift */; }; 70C4A4851DA753100037FF8C /* ProvinceTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70C4A4841DA753100037FF8C /* ProvinceTableViewCell.swift */; }; @@ -42,6 +43,7 @@ /* Begin PBXFileReference section */ 706FBAA61DB446E300B7F984 /* AppCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppCoordinator.swift; sourceTree = ""; }; + 709EF18C1E1F22A70095FE96 /* Region.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Region.swift; sourceTree = ""; }; 70C4A47E1DA6FC160037FF8C /* PersistenceManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersistenceManager.swift; sourceTree = ""; }; 70C4A4801DA701F80037FF8C /* RegionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegionManager.swift; sourceTree = ""; }; 70C4A4841DA753100037FF8C /* ProvinceTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProvinceTableViewCell.swift; sourceTree = ""; }; @@ -92,6 +94,7 @@ isa = PBXGroup; children = ( 70C4A4801DA701F80037FF8C /* RegionManager.swift */, + 709EF18C1E1F22A70095FE96 /* Region.swift */, 70C4A47E1DA6FC160037FF8C /* PersistenceManager.swift */, ); name = Model; @@ -241,7 +244,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0800; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Napp Development"; TargetAttributes = { 70D6B2B41DA43BCD00694B14 = { @@ -318,6 +321,7 @@ 706FBAA71DB446E300B7F984 /* AppCoordinator.swift in Sources */, 70C4A4811DA701F80037FF8C /* RegionManager.swift in Sources */, 70C4A47F1DA6FC160037FF8C /* PersistenceManager.swift in Sources */, + 709EF18D1E1F22A70095FE96 /* Region.swift in Sources */, 70D6B2BC1DA43BCD00694B14 /* The_Plate_Game.xcdatamodeld in Sources */, 70D6B2B91DA43BCD00694B14 /* AppDelegate.swift in Sources */, 70D6B2BE1DA43BCD00694B14 /* ProvinceListTableViewController.swift in Sources */, @@ -388,6 +392,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -438,6 +443,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; diff --git a/The Plate Game/ProvinceListTableViewController.swift b/The Plate Game/ProvinceListTableViewController.swift index b42b9af..2072329 100644 --- a/The Plate Game/ProvinceListTableViewController.swift +++ b/The Plate Game/ProvinceListTableViewController.swift @@ -12,7 +12,7 @@ protocol ProvinceListTableViewControllerDelegate { func didSelect(province: Province) } -class ProvinceListTableViewController: UITableViewController, RegionManagerDelegate { +class ProvinceListTableViewController: UITableViewController, RegionManagerDelegate, UISearchBarDelegate { private let regionManager: RegionManager @@ -34,6 +34,16 @@ class ProvinceListTableViewController: UITableViewController, RegionManagerDeleg fatalError("init(coder:) has not been implemented") } + override func loadView() { + super.loadView() + + let searchBar = UISearchBar(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 44)) + searchBar.delegate = self + searchBar.showsCancelButton = false + + tableView.tableHeaderView = searchBar + } + override func viewDidLoad() { super.viewDidLoad() @@ -76,7 +86,7 @@ class ProvinceListTableViewController: UITableViewController, RegionManagerDeleg } override func numberOfSections(in tableView: UITableView) -> Int { - return regionManager.regions.count + return regionManager.count } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { @@ -123,5 +133,39 @@ class ProvinceListTableViewController: UITableViewController, RegionManagerDeleg regionManager.mark(province: province, asFound: !province.isFound) } + + // MARK: - Search Bar Delegate + + func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { + regionManager.searchQuery = searchText.isEmpty ? nil : searchText + + tableView.reloadData() + } + + func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) { + searchBar.setShowsCancelButton(true, animated: true) + } + + func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { + finishSearch(searchBar) + } + + func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { + if let _ = regionManager.searchQuery { + regionManager.searchQuery = nil + tableView.reloadData() + } + + finishSearch(searchBar) + } + + func searchBarTextDidEndEditing(_ searchBar: UISearchBar) { + finishSearch(searchBar) + } + + func finishSearch(_ searchBar: UISearchBar) { + searchBar.setShowsCancelButton(false, animated: true) + searchBar.resignFirstResponder() + } } diff --git a/The Plate Game/Region.swift b/The Plate Game/Region.swift new file mode 100644 index 0000000..ae20996 --- /dev/null +++ b/The Plate Game/Region.swift @@ -0,0 +1,25 @@ +// +// Region.swift +// The Plate Game +// +// Created by Connor Krupp on 1/5/17. +// Copyright © 2017 Napp Development. All rights reserved. +// + +import Foundation + +enum region: String { + case us = "United States" + case canada = "Canada" + + static func forSection(_ index: Int) -> region { + switch index { + case 0: + return .us + case 1: + return .canada + default: + fatalError("Invalid index for region") + } + } +} diff --git a/The Plate Game/RegionManager.swift b/The Plate Game/RegionManager.swift index da72ec5..0d9c13d 100644 --- a/The Plate Game/RegionManager.swift +++ b/The Plate Game/RegionManager.swift @@ -12,40 +12,36 @@ protocol RegionManagerDelegate { func regionManager(_ regionManager: RegionManager, didUpdateFoundProvinceCount count: Int) } -enum region: String { - case us = "United States" - case canada = "Canada" - - static func forSection(_ index: Int) -> region { - switch index { - case 0: - return .us - case 1: - return .canada - default: - fatalError("Invalid index for region") - } - } -} - final class RegionManager { private var persistenceManager: PersistenceManager - private(set) var regions: [region:[Province]] + private(set) var unfilteredRegions: [region:[Province]] + private(set) var filteredRegions: [region:[Province]] + + var searchQuery: String? { + didSet { + if let query = searchQuery { + filteredRegions = filter(regions: unfilteredRegions, query: query) + } else { + filteredRegions = unfilteredRegions + } + } + } var provincesRemaining: Int { - var count = 0 - for (_, provinces) in regions { - count += provinces.filter({!$0.isFound}).count + return unfilteredRegions.reduce(0) { sum, tuple in + sum + tuple.value.reduce(0) { sum, province in + province.isFound ? sum : sum + 1 + } } - return count } var delegate: RegionManagerDelegate? init(persistenceManager: PersistenceManager) { self.persistenceManager = persistenceManager - self.regions = persistenceManager.getRegions() + self.unfilteredRegions = persistenceManager.getRegions() + self.filteredRegions = unfilteredRegions } func mark(province: Province, asFound isFound: Bool) { @@ -55,15 +51,36 @@ final class RegionManager { delegate?.regionManager(self, didUpdateFoundProvinceCount: provincesRemaining) } + var count: Int { + return filteredRegions.count + } + func provinces(forRegion region: region) -> [Province] { - return regions[region] ?? [] + return filteredRegions[region] ?? [] } func province(at indexPath: IndexPath) -> Province { - guard let province = regions[region.forSection(indexPath.section)]?[indexPath.row] else { + guard let province = filteredRegions[region.forSection(indexPath.section)]?[indexPath.row] else { fatalError("Invalid IndexPath") } return province } + + private func filter(regions: [region:[Province]], query: String) -> [region:[Province]] { + + var filteredRegions = [region:[Province]]() + + for (region, provinces) in regions { + let filteredProvinces = provinces.filter({ province in + return province.name?.lowercased().contains(query.lowercased()) ?? false + }) + + if filteredProvinces.count > 0 { + filteredRegions[region] = filteredProvinces + } + } + + return filteredRegions + } } diff --git a/The Plate Game/SettingsTableViewController.swift b/The Plate Game/SettingsTableViewController.swift new file mode 100644 index 0000000..1cfc8a7 --- /dev/null +++ b/The Plate Game/SettingsTableViewController.swift @@ -0,0 +1,9 @@ +// +// SettingsTableViewController.swift +// The Plate Game +// +// Created by Connor Krupp on 1/5/17. +// Copyright © 2017 Napp Development. All rights reserved. +// + +import Foundation