CocoaTouch 开发 - GaoZhenWei/SwiftLearning GitHub Wiki
1. UITableView的使用关键点记录
1.1 UITableView vs UITableViewController
UITableView是一个UIView的子类,需要将其放到ViewController中,并手动设置其delegate与datasourceUITableViewController是一个继承自UIViewController的试图控制器,它自动包含了一个UITableView作为其view,而且自动关联了delegate和datasource到它自身UITableView使用起来更加的灵活,可以布置复杂的布局,但是需要我们手动设置其delegate与datasource,并实现其方法UITableViewController就只能用于创建只使用UITableView的控制器,相对限制了我们的UI界面。- 在日常开发过程中,尽量使用
UITableView来应对经常变化的需求
1.2 UITableViewCell的复用机制
苹果为了减少内存的消耗与界面的流畅性,引入了Cell的复用机制,其使用步骤为:
- Step 1:在
viewDidLoad中使用方法registerClass:forCellReuseIdentifier:注册需要复用的Cell类并指定一个CellReuseIdentifier:
let CellIdentifier = "MyFirstTableViewCell"
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: CellIdentifier)
}
- Step 2:在
cellForRowAtIndexPath方法中,使用dequeueReusableCellWithIdentifier:forIndexPath:来获取到一个可以复用的Cell:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier, forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = data[indexPath.row]
return cell
}
Notes:在复用某个Cell类时,一定要先在viewDidLoad中先注册这个类以及用来复用的CellIdentifier,否则程序会Crash。
1.3 创建UITableViewCell的子类,实现自定义Cell
方式一:在Storyboard中创建并实现自定义Cell的UI布局
- Step 1:创建一个集成在
UITableViewCell的子类的Swift文件 - Step 2:在
Storyboard中拖入一个Cell,并设置其Custom Class为上一步创建的Swift类 - Step 3:在
Storyboard中选中这个Cell,在属性栏的identifier中指定一个CellIdentifier - Step 4:在
cellForRowAtIndexPath方法中,使用dequeueReusableCellWithIdentifier:forIndexPath:来获取到一个可以复用的Cell,同时需要将默认的UITableViewCell转换为自定义的Swift类型:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("com.codepath.DemoPrototypeCell", forIndexPath: indexPath) as DemoPrototypeCell
let cityState = data[indexPath.row].componentsSeparatedByString(", ")
cell.cityLabel.text = cityState.first
cell.stateLabel.text = cityState.last
return cell
}
Notes:使用Storyboard布局的自定义Cell,无须在viewDidLoad中注册,只需要在Storyboard的属性栏中为其指定一个CellIdentifier即可。
方式二:为自定义Cell创建一个单独的Xib文件进行UI布局
如果项目没有使用Storyboard,可以创建一个NIB文件来进行布局,和在Storyboard中设置Cell一样,也需要设置其Custom Class。不一样的地方在于:无须指定其identifier,指定了也是没用的,这是因为在使用这个Cell时,需要先在viewDidLoad中加载并注册这个Nib文件,同时指定一个identifier:
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
let cellNib = UINib(nibName: "DemoNibTableViewCell", bundle: NSBundle.mainBundle())
tableView.registerNib(cellNib, forCellReuseIdentifier: "MyNibTableViewCell")
}
方式三:使用纯代码为自定义Cell进行UI布局
- Step 1:重写
init(style:reuseIdentifier),在里面添加子视图,并进行布局
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
initViews()
}
- Step 2:重写
drawRect:方法,进行图形的绘制;或者重写layoutSubviews:进行子视图的Frame的设置 - Step 3:在使用此Cell的试图控制器中的
viewDidLoad方法中,进行注册类以及复用时的identifier:
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.registerClass(DemoProgrammaticTableViewCell.self, forCellReuseIdentifier: "MyProgrammaticCell")
}
1.4 自定义的UITableViewCell的子类响应selected的方式
- 首先,最基本的可以设置cell的
selectionStyle - 通过
UITableView的allowsSelection来控制是否能被选中 - 通过设置Cell的
selectedBackgroundView属性来改变Cell被选中时的背景 - 在自定义的Cell类中,重写
setSelected方法来执行Cell被选中时的一些操作
import UIKit
class DemoProgrammaticTableViewCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
initViews()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initViews()
}
func initViews() {
selectedBackgroundView=UIView(frame: frame)
selectedBackgroundView.backgroundColor = UIColor(red: 0.5, green: 0.7, blue: 0.9, alpha: 0.8)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
let fontSize: CGFloat = selected ? 34.0 : 17.0
self.textLabel?.font = self.textLabel?.font.fontWithSize(fontSize)
}
}
1.5 UIRefreshControl--下拉刷新控件的使用
1.5.1 在UITableViewController中使用
UIKit中提供了这个标准的下拉刷新控件,但是这个控件是被设计用于UITableViewController及其子类中,其使用方式如下:
class TableViewController: UITableViewController {
var stories: [Story] = []
override func viewDidLoad() {
super.viewDidLoad()
fetchStories()
refreshControl = UIRefreshControl()
refreshControl?.addTarget(self, action: "fetchStories", forControlEvents: UIControlEvents.ValueChanged)
}
func fetchStories() {
Story.fetchStories({ (stories: [Story]) -> Void in
dispatch_async(dispatch_get_main_queue(), {
self.stories = stories
self.tableView.reloadData()
self.refreshControl?.endRefreshing()
})
}, error: nil)
}
...
}
1.5.2 在__非__UITableViewController中使用
虽然此控件被设计用于UITableViewController中,但是我们可以稍微做一些“手脚”,就能够使用到其他的视图控制器中:
class ViewController: UIViewController, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
var refreshControl: UIRefreshControl!
var stories: [Story] = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: "fetchStories", forControlEvents: UIControlEvents.ValueChanged)
let dummyTableVC = UITableViewController()
dummyTableVC.tableView = tableView
dummyTableVC.refreshControl = refreshControl
}
}