-
Notifications
You must be signed in to change notification settings - Fork 912
/
RootViewController.swift
155 lines (135 loc) · 6.15 KB
/
RootViewController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import UIKit
// I don't see how else to asset that the status bar should be hidden,
// other than to write my own UISearchController subclass
class MySearchController : UISearchController {
override var prefersStatusBarHidden : Bool {
return true
}
}
class RootViewController : UITableViewController, UISearchBarDelegate {
var sectionNames = [String]()
var sectionData = [[String]]()
var searcher : UISearchController!
override var prefersStatusBarHidden : Bool {
return true
}
override func viewDidLoad() {
let s = try! String(contentsOfFile: Bundle.main.path(forResource: "states", ofType: "txt")!)
let states = s.components(separatedBy:"\n")
var previous = ""
for aState in states {
// get the first letter
let c = String(aState.characters.prefix(1))
// only add a letter to sectionNames when it's a different letter
if c != previous {
previous = c
self.sectionNames.append( c.uppercased() )
// and in that case also add new subarray to our array of subarrays
self.sectionData.append( [String]() )
}
sectionData[sectionData.count-1].append( aState )
}
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
self.tableView.register(UITableViewHeaderFooterView.self, forHeaderFooterViewReuseIdentifier: "Header")
self.tableView.sectionIndexColor = .white
self.tableView.sectionIndexBackgroundColor = .red
// self.tableView.sectionIndexTrackingBackgroundColor = .blue
self.tableView.backgroundColor = .yellow // but the search bar covers that
self.tableView.backgroundView = { // this will fix it
let v = UIView()
v.backgroundColor = .yellow
return v
}()
// most rudimentary possible search interface
// instantiate a view controller that will present the search results
let src = SearchResultsController(data: self.sectionData)
// instantiate a search controller and keep it alive
let searcher = MySearchController(searchResultsController: src)
self.searcher = searcher
// specify who the search controller should notify when the search bar changes
searcher.searchResultsUpdater = src
// put the search controller's search bar into the interface
let b = searcher.searchBar
b.sizeToFit() // crucial, trust me on this one
// b.scopeButtonTitles = ["Hey", "Ho"] // shows during search only; uncomment to see
// (not used in this example; just showing the interface)
// WARNING: do NOT call showsScopeBar! it messes things up!
// (buttons will show during search if there are titles)
b.autocapitalizationType = .none
self.tableView.tableHeaderView = b
self.tableView.reloadData()
self.tableView.scrollToRow(at:
IndexPath(row: 0, section: 0),
at:.top, animated:false)
// that's all! The rest is in SearchResultsController
}
override func numberOfSections(in tableView: UITableView) -> Int {
return self.sectionNames.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.sectionData[section].count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:"Cell", for: indexPath)
let s = self.sectionData[indexPath.section][indexPath.row]
cell.textLabel!.text = s
// this part is not in the book, it's just for fun
var stateName = s
stateName = stateName.lowercased()
stateName = stateName.replacingOccurrences(of:" ", with:"")
stateName = "flag_\(stateName).gif"
let im = UIImage(named: stateName)
cell.imageView!.image = im
return cell
}
/*
override func tableView(_ tableView: UITableView!, titleForHeaderInSection section: Int) -> String! {
return self.sectionNames[section]
}
*/
// this is more "interesting"
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let h = tableView
.dequeueReusableHeaderFooterView(withIdentifier:"Header")!
if h.tintColor != .red {
h.tintColor = .red // invisible marker, tee-hee
h.backgroundView = UIView()
h.backgroundView?.backgroundColor = .black
let lab = UILabel()
lab.tag = 1
lab.font = UIFont(name:"Georgia-Bold", size:22)
lab.textColor = .green
lab.backgroundColor = .clear
h.contentView.addSubview(lab)
let v = UIImageView()
v.tag = 2
v.backgroundColor = .black
v.image = UIImage(named:"us_flag_small.gif")
h.contentView.addSubview(v)
lab.translatesAutoresizingMaskIntoConstraints = false
v.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
NSLayoutConstraint.constraints(withVisualFormat:
"H:|-5-[lab(25)]-10-[v(40)]",
metrics:nil, views:["v":v, "lab":lab]),
NSLayoutConstraint.constraints(withVisualFormat:
"V:|[v]|",
metrics:nil, views:["v":v]),
NSLayoutConstraint.constraints(withVisualFormat:
"V:|[lab]|",
metrics:nil, views:["lab":lab])
].flatMap{$0})
}
let lab = h.contentView.viewWithTag(1) as! UILabel
lab.text = self.sectionNames[section]
return h
}
/*
override func tableView(_ tableView: UITableView!, willDisplayHeaderView view: UIView!, forSection section: Int) {
println(view) // prove we are reusing header views
}
*/
override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return self.sectionNames
}
}