天天看點

iOS 清單 UITableView 提速指南

UITableview

從08年到現在開發過的iOS應用不計其數了,但是面試很多人的時候,發現依然很多同學在最基本的清單控件上懂得不夠深,下面就結合各方面的資料進行再一次講解。

我們都知道純代碼是效率最高的,但是在開發成本上已經越來越不如使用Storyboard成本效益高,速度快,是以本文試圖結合UIStoryboard來描述一整套方案。

簡單配置

在Storyboard中拖入UITableViewController,并且修改塗塗畫畫。

在代碼區new File生成一個基于UITableviewController的自定義類,我這裡暫時取名為Home。因為首頁就是一個複雜的清單的不在少數吧?呵呵。

然後在Identity insepctor裡修改對應的Class name,使得代碼與Storyboard産生關聯。

iOS 清單 UITableView 提速指南

想要做下拉重新整理嘛?系統自帶了一個給你,并且可以自定義換标題哦。很多人真的不知道在哪兒選中,請看下圖,先選中UITableviewController,然後在頁籤中enable這個refresh選項,就自動完成了。 對應的代碼還是複制進去,就會自動觸發。

iOS 清單 UITableView 提速指南

然後你需要對UITableView做一些簡單的配置,首先要選中UITableView,很多人看不到選項,是因為預設關閉了……

iOS 清單 UITableView 提速指南

下圖是對UITableview的簡單配置。

Content是動态清單/靜态清單,如果是靜态的,那你基本不用寫代碼就能所見即所得,譬如“設定”頁面就可以套用。但是諸如微網誌啦,朋友圈,還是老實的用動态清單,用代碼控制。

Prototype Cells指會出現的cell有幾種類型。這個後面再講。

Style效果現場試一下就看出來了。Separator指的分隔行樣式。

iOS 清單 UITableView 提速指南

然後你就需要代碼中做一些簡單的配置了,我隻列重要的,這裡不是基礎教程,基礎的還是老實的看教科書

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView //幾組

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section//每一組分别幾行

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath//每一行多高

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath//每一行分别長啥樣

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath//即将顯示某行

Load More加載更多

加載更多的UITableview擴充控件非常多,嘗試過各種第三方完美擴充後,我覺得這點小把戲也不至于需要擴充UITableview類吧?

那就是在清單追加一個Section,放在最後面,這個Section隻有一個Cell,這個自定義的cell有3種狀态,這些都可以自由發揮。

每當willDisplayCell的時候,你就設定他正在loading狀态,給使用者造成正在加載的假象,同時觸發網絡請求。

當有網絡資料傳回後,自然會insert好多内容,也輪不到這個加載更多的cell顯示的地方了,自然就釋放了。當然了,如果沒有更多内容,也可以輕松的cellForRowAtIndexPath找到唯一的cell,設定為無更多資料等狀态。

typedef enum{

    JWLoadMoreNormal = 0,//點選再加載

    JWLoadMoreLoading,//加載中

    JWLoadMoreDone,//無更多資料

} JWLoadMoreState;

@interface LoadMoreCell : UITableViewCell

@property (strong, nonatomic)  UIView *baseWhiteView;

@property (strong, nonatomic)  UIActivityIndicatorView *activity;

@property (strong, nonatomic)  UILabel *tipsLabel;

@property (strong, nonatomic)  UIButton *loadMoreButton;

@property (nonatomic,unsafe_unretained) id <LoadMoreCellDelegate>                   delegate;

-(void)setupUI;

- (void)loadMore:(id)sender;

-(void)setLoadMoreStatus:(JWLoadMoreState)status;

Autolayout

做完這些,基本配置就完成了,下面需要根據設計師的要求進行自定義開發,譬如自定義cell

iOS 清單 UITableView 提速指南

如上圖,密密麻麻的

autolayout的拖拽不會?你太老土了吧。xcode5的拖拽,可謂是異常簡單,隻需要點快捷菜單的pin,設定好上下左右相對關系就可以了。

建立custom的uitableviewcell基本差不多,拖出來,畫畫塗塗,建立代碼,改類名對應關系,按着“Control”拖拽關聯,等等。

我這裡隻講一個特殊的,就是圖上“圖檔”“摘要”屬于并排區域,可能沒有圖檔的文章,“摘要”就需要頂格排版。這樣的情況該怎麼設定呢?

這就得用NSLayoutConstraint的拽出來的關聯了。把”摘要“的相對距離,鎖定在一個固定的位置上,譬如”左邊欄“,通過少量的代碼計算,即可動态的修改NSLayoutConstraint.constant的距離。

NSString *url=data.img;

[self.previewImageView setClipsToBounds:YES];

if ( url!=nil && ![url isEqualToString:@""]) {  //這裡是判斷有圖沒圖

    [self.previewImageView setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:@"pic_default"]];

    self.previewImageHeight.constant=HomeCellImageHeight;

    self.previewImageWidth.constant=HomeCellImageWidth;

    self.abstractLeftMargin.constant=10;  //若有圖,摘要與圖的左邊距變為10

    self.summaryDistanceBetweenTitle.constant=80;

}

else

{

    [self.previewImageView setImage:nil];

    self.previewImageHeight.constant=0;  //圖檔大小全清空為0

    self.previewImageWidth.constant=0;

    self.abstractLeftMargin.constant=0;  //若無圖,摘要與圖的左邊距變為10

[self setNeedsUpdateConstraints];   //記得強制重新整理,要不然系統懶懶的

[self.contentView layoutIfNeeded];

[self.contentView setNeedsLayout];

動态計算高度

做到這裡,恐怕大部分人都遇到一個門檻了。那就是如何動态計算cell的高度。最簡單的,就是網易新聞類,固定高度。return 44;

若是動态的,無非是建立一個cell,并且初始化構造好,然後輸出cell的最後一行控件的位置,最終給出位置。

但是這就導緻了函數運作的低效。你想,autolayout本來就夠效率低了(因為程式猿省事兒了),再為每一行計算2次,這效率能高?

我親測發現,動态排版效率是非常低的,不足以信任。

最好辦的,還是土方法。擷取對應的資料,根據自己設定的排版規則,動态的計算。土歸土,效率高啊!

        TopicID *data=[threadList objectAtIndex:indexPath.row];

//        NSLog(@"計算行數為%d",indexPath.row);

        int height=0;

        height+=17; //使用者名與頂部空間

        height+=17; //使用者名高度

        height+=8; //使用者名與标題之間距離

        NSString *titleContent=data.title;

        UIFont *titleFont = [UIFont boldSystemFontOfSize:16.0];

        CGSize titleRealSize=[titleContent sizeWithFont:titleFont constrainedToSize:CGSizeMake(280, 150) lineBreakMode:NSLineBreakByTruncatingTail];

        height+=titleRealSize.height;//動态計算标題高度

        if (data.img!=nil && ![data.img isEqualToString:@""]) {

            height+=HomeCellImageHeight;//統計圖的起始點

            height+=20;

//            NSLog(@"有圖");

        }

        else

        {

            NSString *abstract=data.abstract;

            UIFont *abstractFont = [UIFont boldSystemFontOfSize:14.0];

            CGSize abstractRealSize=[abstract sizeWithFont:abstractFont constrainedToSize:CGSizeMake(280, 300) lineBreakMode:NSLineBreakByTruncatingTail];

            height+=abstractRealSize.height;

//            NSLog(@"無圖");

        height+=56; //統計圖的高度

        height+=3;//下邊框的高度

最後别忘了Profile,計算時間,每一個細節的時間優化,最終都會展現在清單的流暢度表現上。 通過以上幾點呢,再結合現成好用的SDWebImageCache,相信大家一定可以做出真正美觀、高效的清單哦!

繼續閱讀