CocoaTouch 开发 - GaoZhenWei/SwiftLearning GitHub Wiki
1. UITableView的使用关键点记录
UITableView
vs UITableViewController
1.1 UITableView
是一个UIView的子类,需要将其放到ViewController
中,并手动设置其delegate与datasourceUITableViewController
是一个继承自UIViewController
的试图控制器,它自动包含了一个UITableView
作为其view,而且自动关联了delegate和datasource到它自身UITableView
使用起来更加的灵活,可以布置复杂的布局,但是需要我们手动设置其delegate与datasource,并实现其方法UITableViewController
就只能用于创建只使用UITableView
的控制器,相对限制了我们的UI界面。- 在日常开发过程中,尽量使用
UITableView
来应对经常变化的需求
UITableViewCell
的复用机制
1.2 苹果为了减少内存的消耗与界面的流畅性,引入了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。
UITableViewCell
的子类,实现自定义Cell
1.3 创建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
即可。
Xib
文件进行UI布局
方式二:为自定义Cell创建一个单独的如果项目没有使用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")
}
UITableViewCell
的子类响应selected
的方式
1.4 自定义的- 首先,最基本的可以设置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)
}
}
UIRefreshControl
--下拉刷新控件的使用
1.5 UITableViewController
中使用
1.5.1 在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)
}
...
}
UITableViewController
中使用
1.5.2 在__非__虽然此控件被设计用于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
}
}