2014年7月1日 星期二

UITableView programmatically using Swift language(Prototype Cell)

【說明】

此份筆記是根據ISBN:978-986-201-900-9這本書的第4~5章節所紀錄的。

使用Prototype Cell呈現TableView的內容。

首先建立一個只有Single View Controller的專案,將自動產生的View Controller刪除,並拖曳Table View Controller進入Storyboard,如下圖所示。

手動拖曳進Storyboard的Table View Controller
將Table View Controller的Custom Class設為CustomTableViewController,如下圖所示。

設定Table View Controller與CustomTableViewController的關聯
將Table View Cell的Style設為Custom,如下圖所示。

將Table View Cell的Style設為Custom
將Table View的Row Height設為71,如下圖所示。

將Table View的Row Height設為71
將Table View Cell的Row Height設為71,並將Custom打勾,如下圖所示。

將Table View Cell的Row Height設為71,並將Custom打勾
拖曳一個Image View至Table View Cell內,並設定X:20、Y:7、Width與Height:58,如下圖所示。

設定Image View的位置與大小
拖曳一個Label至Table View Cell內,並設定X:92、Y:7、Width:215、Height:23,名稱為RecipeName,字型的樣式改為Helvetica Neue Condensed Bold,大小為21,如下圖所示。

設定Label的位置與大小
設定Label的名稱、自行樣式與大小
拖曳一個Label至Table View Cell內,並設定X:92、Y:32、Width:186、Height:33,名稱為PrepTime,如下圖所示。

設定Label的位置與大小
完成的Prototype Cell,如下圖所示。

自訂的Prototype Cell
為自訂的Cell建立一個類別,並宣告一個UIImageView與兩個UILabel的IBOutlet,如下圖所示。

新建自訂的Class
將Prototype Cell的Class設為CustomTableCell,如下圖所示。

設定Prototype Cell的Class
設定Prototype Cell得Identifier為CustomTableCell,如下圖所示。

設定Prototype Cell的Identifier
建立類別屬性及介面中UIImageView與UILabel的連接,如下圖所示,僅以一個Label作為代表。

類別屬性與介面做連接

【片段程式碼】

tableView.contentInset = UIEdgeInsetsMake(20, tableView.contentInset.lefttableView.contentInset.bottom, tableView.contentInset.right)
當Cell View超出至Status bar時可以使用此行程式將View往下調整。

override func tableView(_tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
    return recipesNames.count

}
TableVeiw必須實作的函式,告訴ViewController要顯示多少個Cell。

override func tableView(_tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {

}
這個函式也是必須實作的,告訴ViewController每一列要顯示什麼。

var cellIdentifier: String = "CustomTableCell"
var cell = _tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? CustomTableCell
if cell == nil {
    cell = CustomTableCell(style: .Default, reuseIdentifier: cellIdentifier)

}
這幾段程式是在cellForRowAtIndexPath函式發面,要判別Cell是否已經建立過了,因為TableView受螢幕的限制,一次顯示的Cell不多,所以不可能每一筆資料都建立一個UITableViewCell的物件,而是改變Cell中的Image和Label的文字而已,如此一來可以提升程式的效率。透過dequeueReusableCellWithIdentifier去檢查是否已建立,若回傳Null則新建一個Cell。

override func tableView(_tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
}
這個函式是當Cell被按下時會觸發的,與Button的概念相似。

_tableView.deselectRowAtIndexPath(indexPath, animated: true)
當Cell被按下時會以反灰顯示,若要點完後回復原來的樣子可以使用deselectRowAtIndexPath來恢復。

【完整程式碼】

CustomTableViewController.swift:
//
//  ViewController.swift
//  CustomTable
//
//  Created by Hsu,Yi-Sheng on 2014/7/1.
//  Copyright (c) 2014 yisheng. All rights reserved.
//

import UIKit

class CustomTableViewController: UITableViewController {
                            
    //Data的初始設定
    var recipesNames: String[] = ["Egg Benedict", "Mushroom Risotto", "Full Breakfast", "Hamburger", "Ham and Egg Sandwich", "Creme Brelee", "White Chocolate Donut", "Starbucks Coffee", "Vegetable Curry", "Instant Noodle with Egg", "Noodle with BBQ Pork", "Japanese Noodle with Pork", "Green Tea", "Thai Shrimp Cake", "Angry Birds Cake", "Ham and Cheese Panini"]
    
    var recipesImages: String[] = ["egg_benedict.jpg", "mushroom_risotto.jpg", "full_breakfast.jpg", "hamburger.jpg", "ham_and_egg_sandwich.jpg", "creme_brelee.jpg", "white_chocolate_donut.jpg", "starbucks_coffee.jpg", "vegetable_curry.jpg", "instant_noodle_with_egg.jpg", "noodle_with_bbq_pork.jpg", "japanese_noodle_with_pork.jpg", "green_tea.jpg", "thai_shrimp_cake.jpg", "angry_birds_cake.jpg", "ham_and_cheese_panini.jpg"]
    
    var recipePrepTimes: String[] = ["30 min", "30 min", "20 min", "30 min", "10 min", "1 hour", "45 min", "5 min", "30 min", "8 min", "20 min", "20 min", "5 min", "1.5 hour", "4 hours", "10 min"]
    
    var recipeChecked: Bool[] = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        //cell超過status bar時可以利用此行程式將顯示的地方縮小。
        tableView.contentInset = UIEdgeInsetsMake(20, tableView.contentInset.left, tableView.contentInset.bottom, tableView.contentInset.right)
    }
    
    //設定有幾行
    override func tableView(_tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
        return recipesNames.count
    }
    
    //設定每行的顯示
    override func tableView(_tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
        
        var cellIdentifier: String = "CustomTableCell"
        var cell = _tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? CustomTableCell
        if cell == nil {
            cell = CustomTableCell(style: .Default, reuseIdentifier: cellIdentifier)
        }
        
        cell!.thumbnailImageView.image = UIImage(named: recipesImages[indexPath.row])
        cell!.nameLabel.text = recipesNames[indexPath.row]
        cell!.prepTimeLabel.text = recipePrepTimes[indexPath.row]
        
        if recipeChecked[indexPath.row] {
            cell!.accessoryType = .Checkmark
        } else {
            cell!.accessoryType = .None
        }
        
        return cell
    }
    
    override func tableView(_tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
        
        var alertView = UIAlertController(title: recipesNames[indexPath.row], message: recipePrepTimes[indexPath.row], preferredStyle: .Alert)
        alertView.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
        self.presentViewController(alertView, animated: true, completion: nil)
        
        var cell: UITableViewCell = _tableView.cellForRowAtIndexPath(indexPath)
        cell.accessoryType = .Checkmark
        
        if (recipeChecked[indexPath.row]) {
            recipeChecked[indexPath.row] = false
            cell.accessoryType = .None
        } else {
            recipeChecked[indexPath.row] = true
            cell.accessoryType = .Checkmark
        }
        
        _tableView.deselectRowAtIndexPath(indexPath, animated: true)
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

CustomTableCell.swift:
//
//  CustomTableCell.swift
//  CustomTable
//
//  Created by Hsu,Yi-Sheng on 2014/7/1.
//  Copyright (c) 2014 yisheng. All rights reserved.
//

import UIKit

class CustomTableCell: UITableViewCell {
    
    @IBOutlet var nameLabel: UILabel
    @IBOutlet var prepTimeLabel: UILabel
    @IBOutlet var thumbnailImageView: UIImageView
    

}

【執行結果】

        

【專案範例】

沒有留言:

張貼留言