在移動端應用中,很多情況下我們需要頻繁與表格、列表這類的UI組件打交道,由于移動端設備的屏幕較小,所以在iOS上組織多條信息,UITableView成為了相當得力的助手,下面我們就開始討論一下UITableView在Swift中的實現
通過Xcode中的storyboard
Xcode中Swift開發者提供了很多便捷的工具,比如可以實現拖拽功能的storyboard,在storyboard中,每一個視圖(view)都有一個對應的controller進行管理,因此我們接下來的大部分操作是基于storyboard的
創建List
- 打開項目中的 storyboard, Main.storyboard
打開 utility area 中的 Object library. (或者, 選擇 View > Utilities > Show Object Library.)
在 Object library 中, 找到 Table View Controller 對象.
從列表中拖拽出一個 Table View Controller 對象, 并且將其放置在左側的scene中一個合適的位置上.
- 然后我們直接運行項目,可以查看到表格的視圖已經出現
- image.png
自定義表格單元
-
我們先創建一個自定義表格的控制器類,步驟如下
- 新建一個類
- 選擇iOS標簽卡
- 選擇Cocoa Touch Class
- 選擇SubClass為
UITableViewCell
- 然后選擇語言為Swift
-
然后我們在storyboard中配置Table View中的Cell對應到我們剛才創建的類
image.png 然后我們仍然通過上述的 utility area 中的對象在Cell中拖拽出如下的界面
- image.png
將表格單元與Code關聯
- image.png
通過開發者視圖轉換的方式將XCode的界面調整成如上圖所示
將上述Cell中各元素與上面我們創建的TableViewCell類形成一一對應的關系
//UI中元素在TableViewCell類中的體現
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var photoImageView: UIImageView!
@IBOutlet weak var ratingControl: RatingControl!
加載數據
- 先創建我們的實體對象類,存放的數據內容對應到一個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
}
}
然后我們創建一個
UITableViewController
,MealTableViewController
,我們需要在這個類里面填寫邏輯和處理數據,使數據與綁定的Table View對應我們先定義存儲數據的對象
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()
,需要調用數據初始化方法
override func viewDidLoad() {
super.viewDidLoad()
// Load the sample data.
loadSampleMeals()
}
將數據與表格關聯
- 接下來我們需要將定義好的TableViewController與UI中所需要的DataSource關聯起來
- Table View展示元素所必需的幾個關于DataSource方法如下
func numberOfSections(in tableView: UITableView) -> Int
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
- 重載的方法實現如下
//該方法返回的值代表了Table View需要呈現幾個sections
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
//該方法返回值代表了在該Table View Controller控制下的Table View對應的DataSource有多少數據
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return meals.count
}
//該方法表示了對于每一行Cell,Cell內部的內容應該被如何渲染
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綁定
-
重新啟動項目,觀察到Table中有了我們加入的幾個Cell元素
image.png
通過代碼自定義
通過代碼實現Table View的自定義本質上和上述借助storyboard的方法一樣,實際操作上有一些不同
-
創建一個UITableViewCell(并創建xib)命名為 DemoListCell
image.png -
在DemoListCell.xib中畫出你想要的cell樣式(AutoLayout),另外注意要給Cell制定 IdentityId: DemoListID
image.png 然后類似的,將xib中的自定義元素與Cell的類進行元素綁定
新建一個控制器類
class MainViewController: UIViewController,UITableViewDelegate,UITableViewDataSource
// 定義好DataSource
let cellId = "DemoListID" //獲取CellId
var tableData: (titles:[String], values:[String])? //定義一個數據源
// 在viewDidLoad()方法中創建了Table View
override func viewDidLoad() {
super.viewDidLoad()
self.title = "主頁"
self.view.backgroundColor = UIColor.whiteColor()
//demoList的設置
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指的是我們創建的Cell文件名
self.demoList.registerNib(nib, forCellReuseIdentifier: cellId)
self.demoList.delegate = self
self.demoList.dataSource = self
self.view.addSubview(self.demoList)
self.showData()
}
- 然后重載了相關DataSource的上述的幾個方法
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("沒有數據")
}
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