在移動(dòng)端應(yīng)用中谭期,很多情況下我們需要頻繁與表格、列表這類的UI組件打交道兆旬,由于移動(dòng)端設(shè)備的屏幕較小姻采,所以在iOS上組織多條信息,UITableView成為了相當(dāng)?shù)昧Φ闹志粼鳎旅嫖覀兙烷_始討論一下UITableView在Swift中的實(shí)現(xiàn)
通過Xcode中的storyboard
Xcode中Swift開發(fā)者提供了很多便捷的工具慨亲,比如可以實(shí)現(xiàn)拖拽功能的storyboard,在storyboard中宝鼓,每一個(gè)視圖(view)都有一個(gè)對(duì)應(yīng)的controller進(jìn)行管理刑棵,因此我們接下來的大部分操作是基于storyboard的
創(chuàng)建List
- 打開項(xiàng)目中的 storyboard, Main.storyboard
打開 utility area 中的 Object library. (或者, 選擇 View > Utilities > Show Object Library.)
在 Object library 中, 找到 Table View Controller 對(duì)象.
從列表中拖拽出一個(gè) Table View Controller 對(duì)象, 并且將其放置在左側(cè)的scene中一個(gè)合適的位置上.
- 然后我們直接運(yùn)行項(xiàng)目,可以查看到表格的視圖已經(jīng)出現(xiàn)
自定義表格單元
-
我們先創(chuàng)建一個(gè)自定義表格的控制器類愚铡,步驟如下
- 新建一個(gè)類
- 選擇iOS標(biāo)簽卡
- 選擇Cocoa Touch Class
- 選擇SubClass為
UITableViewCell
- 然后選擇語(yǔ)言為Swift
-
然后我們?cè)趕toryboard中配置Table View中的Cell對(duì)應(yīng)到我們剛才創(chuàng)建的類
然后我們?nèi)匀煌ㄟ^上述的 utility area 中的對(duì)象在Cell中拖拽出如下的界面
將表格單元與Code關(guān)聯(lián)
通過開發(fā)者視圖轉(zhuǎn)換的方式將XCode的界面調(diào)整成如上圖所示
將上述Cell中各元素與上面我們創(chuàng)建的TableViewCell類形成一一對(duì)應(yīng)的關(guān)系
//UI中元素在TableViewCell類中的體現(xiàn)
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var photoImageView: UIImageView!
@IBOutlet weak var ratingControl: RatingControl!
加載數(shù)據(jù)
- 先創(chuàng)建我們的實(shí)體對(duì)象類蛉签,存放的數(shù)據(jù)內(nèi)容對(duì)應(yīng)到一個(gè)Cell
class Meal {
//MARK: Properties
var name: String
var photo: UIImage?
var rating: Int
init?(name: String, photo: UIImage?, rating: Int) {
// The name must not be empty
guard !name.isEmpty else {
return nil
}
// The rating must be between 0 and 5 inclusively
guard (rating >= 0) && (rating <= 5) else {
return nil
}
// Initialize stored properties.
self.name = name
self.photo = photo
self.rating = rating
}
}
然后我們創(chuàng)建一個(gè)
UITableViewController
,MealTableViewController
沥寥,我們需要在這個(gè)類里面填寫邏輯和處理數(shù)據(jù)碍舍,使數(shù)據(jù)與綁定的Table View對(duì)應(yīng)我們先定義存儲(chǔ)數(shù)據(jù)的對(duì)象
meals
,并定義初始化方法
var meals = [Meal]()
private func loadSampleMeals() {
let photo1 = UIImage(named: "meal1")
let photo2 = UIImage(named: "meal2")
let photo3 = UIImage(named: "meal3")
guard let meal1 = Meal(name: "Caprese Salad", photo: photo1, rating: 4) else {
fatalError("Unable to instantiate meal1")
}
guard let meal2 = Meal(name: "Chicken and Potatoes", photo: photo2, rating: 5) else {
fatalError("Unable to instantiate meal2")
}
guard let meal3 = Meal(name: "Pasta with Meatballs", photo: photo3, rating: 3) else {
fatalError("Unable to instantiate meal2")
}
meals += [meal1, meal2, meal3]
}
- 然后在TableViewController中重載父類方法
viewDidLoad()
邑雅,需要調(diào)用數(shù)據(jù)初始化方法
override func viewDidLoad() {
super.viewDidLoad()
// Load the sample data.
loadSampleMeals()
}
將數(shù)據(jù)與表格關(guān)聯(lián)
- 接下來我們需要將定義好的TableViewController與UI中所需要的DataSource關(guān)聯(lián)起來
- Table View展示元素所必需的幾個(gè)關(guān)于DataSource方法如下
func numberOfSections(in tableView: UITableView) -> Int
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
- 重載的方法實(shí)現(xiàn)如下
//該方法返回的值代表了Table View需要呈現(xiàn)幾個(gè)sections
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
//該方法返回值代表了在該Table View Controller控制下的Table View對(duì)應(yīng)的DataSource有多少數(shù)據(jù)
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return meals.count
}
//該方法表示了對(duì)于每一行Cell片橡,Cell內(nèi)部的內(nèi)容應(yīng)該被如何渲染
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "MealTableViewCell"
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? MealTableViewCell else {
fatalError("The dequeued cell is not an instance of MealTableViewCell.")
}
// Fetches the appropriate meal for the data source layout.
let meal = meals[indexPath.row]
cell.nameLabel.text = meal.name
cell.photoImageView.image = meal.photo
cell.ratingControl.rating = meal.rating
return cell
}
- 將Controller與UI綁定
-
重新啟動(dòng)項(xiàng)目,觀察到Table中有了我們加入的幾個(gè)Cell元素
通過代碼自定義
通過代碼實(shí)現(xiàn)Table View的自定義本質(zhì)上和上述借助storyboard的方法一樣淮野,實(shí)際操作上有一些不同
-
創(chuàng)建一個(gè)UITableViewCell(并創(chuàng)建xib)命名為 DemoListCell
-
在DemoListCell.xib中畫出你想要的cell樣式(AutoLayout)捧书,另外注意要給Cell制定 IdentityId: DemoListID
然后類似的吹泡,將xib中的自定義元素與Cell的類進(jìn)行元素綁定
新建一個(gè)控制器類
class MainViewController: UIViewController,UITableViewDelegate,UITableViewDataSource
// 定義好DataSource
let cellId = "DemoListID" //獲取CellId
var tableData: (titles:[String], values:[String])? //定義一個(gè)數(shù)據(jù)源
// 在viewDidLoad()方法中創(chuàng)建了Table View
override func viewDidLoad() {
super.viewDidLoad()
self.title = "主頁(yè)"
self.view.backgroundColor = UIColor.whiteColor()
//demoList的設(shè)置
self.demoList.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
//下面代碼是用來去掉UITableView的Cell之間的線
//self.demoList.separatorStyle = UITableViewCellSeparatorStyle.None
let nib = UINib(nibName: "DemoListCell", bundle: nil) //nibName指的是我們創(chuàng)建的Cell文件名
self.demoList.registerNib(nib, forCellReuseIdentifier: cellId)
self.demoList.delegate = self
self.demoList.dataSource = self
self.view.addSubview(self.demoList)
self.showData()
}
- 然后重載了相關(guān)DataSource的上述的幾個(gè)方法
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let count:Int = self.tableData!.titles.count else {
print("沒有數(shù)據(jù)")
}
return count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(self.cellId, forIndexPath: indexPath) as! DemoListCell
//cell.cellImg.image = UIImage(named: powerData[indexPath.row][2])
cell.cellLabel.text = self.tableData!.titles[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let index = indexPath.row
let storyID = tableData!.values[index] as String
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var nextView:UIViewController
switch storyID {
case "SCLAlert":
nextView = storyboard.instantiateViewControllerWithIdentifier(storyID) as! SCLAlertDemoViewController
case "SwiftNotice":
nextView = storyboard.instantiateViewControllerWithIdentifier(storyID) as! SwiftNoticeDemoViewController
case "CNPPopup":
nextView = storyboard.instantiateViewControllerWithIdentifier(storyID) as! CNPPopupDemoViewController
case "ClosureBack":
nextView = LWRootViewController()
default:
nextView = storyboard.instantiateViewControllerWithIdentifier("SCLAlert") as! SCLAlertDemoViewController
}
self.navigationController?.pushViewController(nextView, animated: true)
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
return 50
}
參考資料
Swift編程(一):UITableView及自定義Cell的Xib
Start Developing iOS (Swift) : Create a Table View