UITableView計算cell高度的幾種方法

為了好看配張圖

前言

在iOS開發(fā)中UITableView有很多需要注意的坑,這篇文章主要總結一下計算cell高度的幾種方式,并且分析一下每種方式的優(yōu)缺點..請結合demo一起看
demo地址:https://github.com/Lafree317/ZECellHightDemo

上代碼

因為網(wǎng)絡層和Model層是通用的所以提前看一眼
網(wǎng)絡層:通用的網(wǎng)絡接口,抓取自知乎日報首頁..

import UIKit
import SwiftyJSON
import AFNetworking

typealias HomeModelBlock = (homeModel:HomeModel) -> Void

class Helper: NSObject {
    /**
     抓取知乎日報首頁
     
     - parameter callBack: 回調(diào)一個HomeModel
     */
    internal func getData(callBack:HomeModelBlock){
        // AFNetWorking請求數(shù)據(jù)
        let url =  "http://news-at.zhihu.com/api/4/news/latest"
        let manager = AFHTTPSessionManager()
        manager.GET(url, parameters: nil, progress: nil, success: { (dataTask, anyobject) in
            
            let json = JSON(anyobject!)
            let top_stories = self.jsonToNewsArr(json["top_stories"].arrayValue)
            let date = json["date"].stringValue
            let stories = self.jsonToNewsArr(json["stories"].arrayValue)
            let homeModel = HomeModel(top_stories: top_stories, date: date, stories: stories)
            
            callBack(homeModel: homeModel)
        }) { (dataTask, error) in
            // 暫不處理錯誤
        }
    }
    /**
     傳入解析一個json數(shù)組,返回一個model數(shù)組
     
     - parameter jsonArr: SwiftyJSON解析出來的json數(shù)組
     
     - returns: NewsModel數(shù)組
     */
    func jsonToNewsArr(jsonArr:[JSON]) -> Array<NewsModel> {
        var newsArr:Array<NewsModel> = []
        for i in 0 ..< jsonArr.count {
            let id = jsonArr[i]["id"].intValue
            let title = jsonArr[i]["title"].stringValue
            var image = jsonArr[i]["image"].stringValue
            // 有的圖片是數(shù)組,暫時不處理,只取出一張
            if image == "" {
                image = jsonArr[i]["images"].arrayValue[0].stringValue
            }
            let type =  jsonArr[i]["type"].intValue
            let ga_prefix = jsonArr[i]["ga_prefix"].stringValue
            let newModel = NewsModel(id: id, title: title, image: image, type: type, ga_prefix: ga_prefix)
            newsArr.append(newModel)
        }
        return newsArr
    }
}

Model層:按照請求返回的json格式創(chuàng)建一個struct

// 知乎日報首頁model
struct HomeModel {
    let top_stories:Array<NewsModel> // 置頂內(nèi)容
    let date:String // 日期
    let stories:Array<NewsModel> // 今日內(nèi)容
    
    // 返回一整個數(shù)組
    func getDataArr() -> Array<NewsModel> {
        return top_stories + stories
    }
}

struct NewsModel {
    let id:Int
    let title:String // 標題
    let image:String // 圖片地址
    let type:Int
    let ga_prefix:String
    
    // 獲取cell的高度
    func getCellHeight() -> CGFloat {
        var cellHeight:CGFloat = 0
        let imageHeight:CGFloat = 200
        let margin:CGFloat = 8 // label距離上下左右各為8
        
        // 計算title高度方法
        let size = CGSizeMake(UIScreen.mainScreen().bounds.width - margin*2 ,0)
        let titleHeight = title.boundingRectWithSize(size, options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName:UIFont.systemFontOfSize(20)], context: nil).height
        
        cellHeight = imageHeight + titleHeight + margin*2 + 1 //+1才換行...可能是cell分割線吧....
        
        return cellHeight
    }
}

開始正題

通過model計算高度

Model內(nèi)生成一個計算方法,通過model內(nèi)的屬性計算高度.這種方式應該是最穩(wěn)妥的

    // 獲取cell的高度
    func getCellHeight() -> CGFloat {
        var cellHeight:CGFloat = 0
        let imageHeight:CGFloat = 200
        let margin:CGFloat = 8 // label距離上下左右各為8
        
        // 計算title高度方法
        let size = CGSizeMake(UIScreen.mainScreen().bounds.width - margin*2 ,0)
        let titleHeight = title.boundingRectWithSize(size, options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName:UIFont.systemFontOfSize(20)], context: nil).height
        
        cellHeight = imageHeight + titleHeight + margin*2 + 1 //+1才換行...可能是cell分割線吧....
        
        return cellHeight
    }

缺點:如果計算量太大代碼會很難讀懂,不好改

通過持有Cell計算高度

給cell賦值的時候直接改變cell的contentView.frame,通過controller里再多持有一個cell,每次需要計算高度的時候給自己持有的也賦值一次然后直接返回cell的高

// 現(xiàn)在controller里創(chuàng)建一個cell屬性并且初始化
cell = NSBundle.mainBundle().loadNibNamed("RetainCell", owner: self, options: nil).first as! RetainCell
// 最好新寫一個方法,如果都走賦值方法的話會容易引發(fā)問題
func getCellHeight(model:NewsModel) -> CGFloat{
    self.buttomLabel.text = model.title
    // 下面兩個方法都是必要的
    self.buttomLabel.layoutIfNeeded()
    self.buttomLabel.sizeToFit() // 讓label自適應
    // 更改 contentView.frame
    var rect = self.contentView.frame
    rect.size.height = CGRectGetMaxY(buttomLabel.frame) + 8
    self.contentView.frame = rect
    return self.contentView.frame.height
}
// 在tableView返回cell高度時
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return cell.getCellHeight(dataArr[indexPath.row])
}

缺點:每次計算高度時都要給cell賦值兩次,性能太低,在某些情況下會對屏幕適配上出問題...網(wǎng)上流傳這種方法真是坑人...也許是本菜雞不會用..希望大家指正

通過可視化計算cell高度

通過AutoLayout的約束給每個控件定義優(yōu)先級,如果需要再某些地方再次更改高度可以在代碼中更改約束的內(nèi)容然后layoutIfNeed
先給label的高度設置為>=32

// 然后設置tableView.rowHeight
self.tableView.rowHeight = UITableViewAutomaticDimension
// 只用設置一個預估高度
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return 258//預估高度
}

缺點:這種方式在我自己敲demo的時候一直在用,還沒有碰到缺點...不過按照慣例一定有坑,只是我還沒踩到而已..(可能需求太變態(tài)的時候不好做)

庫計算

SDAutoLayout等庫會自動計算Cell高度

固定高度

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌呜笑,老刑警劉巖由桌,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扯旷,死亡現(xiàn)場離奇詭異庙洼,居然都是意外死亡赵讯,警方通過查閱死者的電腦和手機栏赴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門蘑斧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人艾帐,你說我怎么就攤上這事乌叶。” “怎么了柒爸?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵准浴,是天一觀的道長。 經(jīng)常有香客問我捎稚,道長乐横,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任今野,我火速辦了婚禮葡公,結果婚禮上,老公的妹妹穿的比我還像新娘条霜。我一直安慰自己催什,他們只是感情好,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布宰睡。 她就那樣靜靜地躺著蒲凶,像睡著了一般气筋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上旋圆,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天宠默,我揣著相機與錄音,去河邊找鬼灵巧。 笑死搀矫,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的刻肄。 我是一名探鬼主播瓤球,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼敏弃!你這毒婦竟也來了冰垄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤权她,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后逝薪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體隅要,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年董济,在試婚紗的時候發(fā)現(xiàn)自己被綠了步清。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡虏肾,死狀恐怖廓啊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情封豪,我是刑警寧澤谴轮,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站吹埠,受9級特大地震影響第步,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缘琅,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一粘都、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刷袍,春花似錦翩隧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽专缠。三九已至,卻和暖如春顽频,著一層夾襖步出監(jiān)牢的瞬間藤肢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工糯景, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嘁圈,地道東北人。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓蟀淮,卻偏偏與公主長得像最住,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子怠惶,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 2017.02.22 可以練習涨缚,每當這個時候,腦袋就犯困策治,我這腦袋真是神奇呀脓魏,一說讓你做事情,你就犯困通惫,你可不要太...
    Carden閱讀 1,337評論 0 1
  • iOS網(wǎng)絡架構討論梳理整理中茂翔。。履腋。 其實如果沒有APIManager這一層是沒法使用delegate的珊燎,畢竟多個單...
    yhtang閱讀 5,174評論 1 23
  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫、插件遵湖、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,066評論 4 62
  • 今天心情不太好悔政,于是就出去隨便逛逛,不知不覺上了輛公交車延旧,那是個7.8點的夜晚谋国,燈火輝煌,車水馬龍迁沫。走到最后排一個...
    拾憶貝殼閱讀 126評論 0 0
  • “媽了烹卒!”何紲茗把空了的啤酒罐重重地摔在墻上,隨即無力地癱坐在了地上弯洗。窗戶外長明的街燈把他的影子模糊地壓在了墻上...
    墨凡字間閱讀 371評論 0 0