Empty Data set for search controllers

This commit is contained in:
Chris Li 2016-09-28 17:00:22 -04:00
parent 1cc5ca6ded
commit eff2d2203a
7 changed files with 132 additions and 94 deletions

View File

@ -10,9 +10,8 @@ import UIKit
import CoreData
import DZNEmptyDataSet
class SearchBooksController: UIViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate, TableCellDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate {
class SearchBooksController: SearchTableViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate, TableCellDelegate {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var recentSearchContainer: DropShadowView!
@IBOutlet weak var recentSearchBarHeight: NSLayoutConstraint!
@ -20,9 +19,6 @@ class SearchBooksController: UIViewController, UITableViewDelegate, UITableViewD
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
// tableView.emptyDataSetSource = self
// tableView.emptyDataSetDelegate = self
tableView.tableHeaderView = UIView()
tableView.tableFooterView = UIView()
tableView.keyboardDismissMode = .OnDrag
}
@ -34,39 +30,12 @@ class SearchBooksController: UIViewController, UITableViewDelegate, UITableViewD
}
func configureRecentSearchBarHeight() {
let previousHeight = recentSearchBarHeight.constant
let newHeight: CGFloat = Preference.recentSearchTerms.count == 0 ? 0.0 : 44.0
guard previousHeight != newHeight else {return}
guard recentSearchBarHeight.constant != newHeight else {return}
recentSearchBarHeight.constant = newHeight
recentSearchContainer.setNeedsDisplay()
}
// MARK: - Empty table datasource & delegate
func titleForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
let text = NSLocalizedString("No Book Available", comment: "Book Library, book downloader, no book center title")
let attributes = [NSFontAttributeName: UIFont.boldSystemFontOfSize(18.0),
NSForegroundColorAttributeName: UIColor.darkGrayColor()]
return NSAttributedString(string: text, attributes: attributes)
}
func buttonTitleForEmptyDataSet(scrollView: UIScrollView!, forState state: UIControlState) -> NSAttributedString! {
let text = NSLocalizedString("Download A Book", comment: "Book Library, book downloader, learn more button text")
let attributes = [NSFontAttributeName: UIFont.boldSystemFontOfSize(17.0), NSForegroundColorAttributeName: UIButton().tintColor]
return NSAttributedString(string: text, attributes: attributes)
}
func verticalOffsetForEmptyDataSet(scrollView: UIScrollView!) -> CGFloat {
return -64.0
}
func spaceHeightForEmptyDataSet(scrollView: UIScrollView!) -> CGFloat {
return 0.0
}
func emptyDataSetDidTapButton(scrollView: UIScrollView!) {
}
// MARK: - Fetched Results Controller
let managedObjectContext = NSManagedObjectContext.mainQueueContext
@ -185,4 +154,25 @@ class SearchBooksController: UIViewController, UITableViewDelegate, UITableViewD
func controllerDidChangeContent(controller: NSFetchedResultsController) {
tableView.endUpdates()
}
// MARK: - DZNEmptyDataSet
func titleForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
let string = NSLocalizedString("No Books Available", comment: "Search, Book Selector")
let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(18), NSForegroundColorAttributeName: UIColor.darkGrayColor()]
return NSAttributedString(string: string, attributes: attributes)
}
func descriptionForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
let string = NSLocalizedString("Please download or import a book.", comment: "Search, Book Selector")
let paragraph = NSMutableParagraphStyle()
paragraph.lineBreakMode = .ByWordWrapping
paragraph.alignment = .Center
let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(14), NSForegroundColorAttributeName: UIColor.lightGrayColor(), NSParagraphStyleAttributeName: paragraph]
return NSAttributedString(string: string, attributes: attributes)
}
func verticalOffsetForEmptyDataSet(scrollView: UIScrollView!) -> CGFloat {
return -(tableView.contentInset.bottom + recentSearchBarHeight.constant) / 2.5
}
}

View File

@ -7,6 +7,7 @@
//
import UIKit
import DZNEmptyDataSet
class SearchController: UIViewController, UISearchBarDelegate, UIGestureRecognizerDelegate {
@ -81,5 +82,44 @@ class SearchController: UIViewController, UISearchBarDelegate, UIGestureRecogniz
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
return touch.view == view ? true : false
}
}
class SearchTableViewController: UIViewController, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate {
@IBOutlet weak var tableView: UITableView!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SearchTableViewController.keyboardDidShow(_:)), name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SearchTableViewController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
tableView.emptyDataSetSource = nil
tableView.emptyDataSetDelegate = nil
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
tableView.emptyDataSetSource = self
tableView.emptyDataSetDelegate = self
}
func keyboardDidShow(notification: NSNotification) {
guard let userInfo = notification.userInfo as? [String: NSValue],
let origin = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().origin else {return}
let point = view.convertPoint(origin, fromView: nil)
let buttomInset = view.frame.height - point.y
tableView.contentInset = UIEdgeInsetsMake(0.0, 0, buttomInset, 0)
tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0, buttomInset, 0)
tableView.reloadEmptyDataSet()
}
func keyboardWillHide(notification: NSNotification) {
tableView.contentInset = UIEdgeInsetsMake(0.0, 0, 0, 0)
tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0, 0, 0)
tableView.reloadEmptyDataSet()
}
}

View File

@ -8,57 +8,35 @@
import UIKit
import Operations
import DZNEmptyDataSet
class SearchResultController: UIViewController, UITableViewDataSource, UITableViewDelegate {
class SearchResultController: SearchTableViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
var searchResults = [SearchResult]()
var shouldShowNoResults = false
var shouldClipRoundCorner: Bool {
return traitCollection.verticalSizeClass == .Regular && traitCollection.horizontalSizeClass == .Regular
}
// MARK: - Override
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
tableView.keyboardDismissMode = .OnDrag
tableView.emptyDataSetSource = self
tableView.emptyDataSetDelegate = self
}
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
tableView.contentInset = UIEdgeInsetsMake(0.0, 0, 0, 0)
tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0, 0, 0)
guard traitCollection != previousTraitCollection else {return}
tableView.layer.cornerRadius = shouldClipRoundCorner ? 10.0 : 0.0
tableView.layer.masksToBounds = shouldClipRoundCorner
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SearchResultController.keyboardDidShow(_:)), name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SearchResultController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
searchResults.removeAll()
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardDidShow(notification: NSNotification) {
guard let userInfo = notification.userInfo as? [String: NSValue] else {return}
guard let keyboardOrigin = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().origin else {return}
let point = view.convertPoint(keyboardOrigin, fromView: UIApplication.appDelegate.window)
let buttomInset = view.frame.height - point.y
tableView.contentInset = UIEdgeInsetsMake(0.0, 0, buttomInset, 0)
tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0, buttomInset, 0)
}
func keyboardWillHide(notification: NSNotification) {
tableView.contentInset = UIEdgeInsetsMake(0.0, 0, 0, 0)
tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0, 0, 0)
}
// MARK: -
func selectFirstResultIfPossible() {
guard searchResults.count > 0 else {return}
@ -66,6 +44,40 @@ class SearchResultController: UIViewController, UITableViewDataSource, UITableVi
tableView(tableView, didSelectRowAtIndexPath: NSIndexPath(forRow: 0, inSection: 0))
}
func reload(results results: [SearchResult]?) {
if let results = results {
searchResults = results
} else {
searchResults.removeAll()
}
tableView.tableFooterView = searchResults.count > 0 ? nil : UIView()
tableView.reloadData()
tableView.reloadEmptyDataSet()
guard searchResults.count > 0 else {return}
self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: true)
}
func startSearch(searchText: String) {
guard searchText != "" else {
shouldShowNoResults = false
reload(results: nil)
return
}
let operation = SearchOperation(searchTerm: searchText)
operation.addObserver(DidFinishObserver {(operation, errors) in
guard let operation = operation as? SearchOperation else {return}
NSOperationQueue.mainQueue().addOperationWithBlock({
self.shouldShowNoResults = true
self.reload(results: operation.results)
})
})
GlobalQueue.shared.add(search: operation)
shouldShowNoResults = false
}
// MARK: - Table view data source
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
@ -112,30 +124,26 @@ class SearchResultController: UIViewController, UITableViewDataSource, UITableVi
GlobalQueue.shared.add(load: operation)
}
// MARK: - Search
// MARK: - DZNEmptyDataSet
func startSearch(searchText: String) {
guard searchText != "" else {
searchResults.removeAll()
tableView.reloadData()
return
}
let operation = SearchOperation(searchTerm: searchText)
operation.addObserver(DidFinishObserver {(operation, errors) in
guard let operation = operation as? SearchOperation else {return}
NSOperationQueue.mainQueue().addOperationWithBlock({
self.searchResults = operation.results
self.tableView.reloadData()
guard operation.results.count > 0 else {return}
self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: true)
})
})
GlobalQueue.shared.add(search: operation)
func titleForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
guard shouldShowNoResults else {return nil}
let string = NSLocalizedString("No Results", comment: "Search, Results")
let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(18), NSForegroundColorAttributeName: UIColor.darkGrayColor()]
return NSAttributedString(string: string, attributes: attributes)
}
func descriptionForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
guard shouldShowNoResults else {return nil}
let string = NSLocalizedString("Please refine your search term.", comment: "Search, Results")
let paragraph = NSMutableParagraphStyle()
paragraph.lineBreakMode = .ByWordWrapping
paragraph.alignment = .Center
let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(14), NSForegroundColorAttributeName: UIColor.lightGrayColor(), NSParagraphStyleAttributeName: paragraph]
return NSAttributedString(string: string, attributes: attributes)
}
func verticalOffsetForEmptyDataSet(scrollView: UIScrollView!) -> CGFloat {
return -tableView.contentInset.bottom / 2.5
}
}
extension LocalizedStrings {
class var searchAddBookGuide: String {return NSLocalizedString("Add a book to get started", comment: "")}
}

View File

@ -49,7 +49,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.8.1275</string>
<string>1.8.1343</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>

View File

@ -276,7 +276,7 @@
<!--Search Result Controller-->
<scene sceneID="g1P-db-EbE">
<objects>
<viewController storyboardIdentifier="SearchResultController" id="fgz-Yy-Pok" customClass="SearchResultController" customModule="Kiwix" customModuleProvider="target" sceneMemberID="viewController">
<viewController storyboardIdentifier="SearchResultController" automaticallyAdjustsScrollViewInsets="NO" id="fgz-Yy-Pok" customClass="SearchResultController" customModule="Kiwix" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="gjd-DF-nun"/>
<viewControllerLayoutGuide type="bottom" id="U6y-Va-LE0"/>

View File

@ -21,7 +21,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.8.1279</string>
<string>1.8.1347</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionMainStoryboard</key>

View File

@ -56,7 +56,7 @@
moduleName = "Kiwix"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Volumes/Data/Developer/Kiwix/Kiwix/Operations/BookmarkMigrationOperation.swift"
timestampString = "496776740.852799"
timestampString = "496789129.532637"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "27"
@ -71,7 +71,7 @@
moduleName = "Kiwix"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Volumes/Data/Developer/Kiwix/Kiwix/Operations/BookmarkMigrationOperation.swift"
timestampString = "496776740.853959"
timestampString = "496789129.534098"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "27"