3.cell常見屬性
tableView展示數(shù)據(jù)的步驟:
1.tableView有一個數(shù)據(jù)源屬性, 如果想充當(dāng)tableView的數(shù)據(jù)源, 必須要遵守對應(yīng)的協(xié)議, 任何對象都可以充當(dāng)TableView的數(shù)據(jù)源, 只要其遵守協(xié)議, 實現(xiàn)相應(yīng)的方法
協(xié)議里面有一些方法, 方法里面最基礎(chǔ)的有一開始的三個方法
屬性:
-
accessoryType
: 屬性作用:
設(shè)置右邊指示器的類型(每一個cell顯示的)例如在設(shè)置中每一個cell
右邊有一個箭頭, 這個箭頭就是指示器
-
UITableViewCellAcessoryDislosureIndicator
指示器為箭頭 -
UITableViewCellAcessoryCheckmark
指示器為對勾 -
[站外圖片上傳中……(1)]
指示器為圓圈箭頭 -
UITableViewCellAccessoryDetailButton
指示器為圓圈i
由于本人的語言不是很生動, 所以上面對指示器描述不是很準確,希望大家自己試試
-
accessoryView
: (如果系統(tǒng)給的指示器不夠用, 我們可以利用這個增加自己需要的控件)
例如:cell.accessoryView = [[UISwich alloc] init];
這個就是一個開關(guān) -
backgroundView
:設(shè)置背景
// 設(shè)置背景(背景view不用設(shè)置尺寸, backgroundView的優(yōu)先級 > backgroundColor)
UIImageView *bgView = [[UIImageView alloc] init];
bgView.image = [UIImage imageNamed:@"buttondelete"];
cell.backgroundView = bgView;
-
selectedBackgroundView
選中時設(shè)置背景
UIView *selectedbgView = [[UIView alloc] init];
selectedbgView.backgroundColor = [UIColor greenColor];
cell.selectedBackgroundView = selectedbgView;
以上的兩段代碼就是如果設(shè)置,我們的背景圖片, 當(dāng)然,設(shè)置背景顏色, 也是類似的. 但是還是有些不同.
04-tableView的常見屬性
1. separatorStyle
:分隔線樣式
每一行都有線, 這個就是分隔線
2. separatorColor
:分隔線顏色
有時候, 我們的顏色種類可能不夠
這個時候, 我們就要了解叫做RGB的東西
顏色有: 32位顏色, 24位顏色
R就是Red ; G就是Green ; B就是Blue
** 32位顏色分為**
- Alpha : 8位(這個是透明)
- Red : 8位
- Green : 8位
- Blue : 8位
** 24位顏色分為**
- Red : 8位
- Green : 8位
- Blue : 8位
然后, 我們在寫程序中需要掌握的是:
我們的顏色是按照十六進制來存儲的, 而且, 他們的存儲方法是是這樣的:
#ff ff ff ff // 這個代表的是白色(所有的顏色, 都是滿格)透明度
前兩個ff代表的是t, 后面的依次是R, G, B
-----------------------------------
#ff 00 00 00 // 這個代表的是黑色, 每一種顏色都是空
注意
- 這里面的黑色是最純潔的
- 白色, 是最不純潔的
- 每一個顏色通道占據(jù)8個二進制位
- 每一個顏色通道的取值范圍是[0, 225]
#ff ff 00 00 // 這個代表的是紅色
之所以講這些, 是由于我們的這個有這么一個方法就是可以根據(jù)你自己的想法設(shè)計顏色
self.tableView.separatorColor = [UIColor colorWithRed: CGFloat green: CGFloat blue: CGFloat alpha: CGFloat];
要注意我在上面每一個參數(shù)的寫法:
self.tableView.separatorColor = [UIColor colorWithRed: 78/225.0 green: 100/225.0 blue: 225/225.0 alpha: 225/225.0];
這個是蘋果官方要求我們這樣寫, 這樣表示的是每一份顏色所占總的比例
3. TableHeadView:
在我們的手機新浪微博中, 這個頭部的控件是用來放置我們的廣告的, 所以以后, 我們再使用的時候, 就不需要增加scollView了
** 調(diào)用方法:**
self.tableView.headView = ......
4. TablefootView:
用來加載更多時候用的, 我們在使用新浪微博, 或者在各大新聞軟件中, 底部會有一個點擊加載的地方
05. cell的循環(huán)利用
1. 分析
**1. ** 其實, 在我們的英雄展示那個程序的時候, 我們其中的一個方法- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
我們都知道, 我們一共有97個英雄, 但是這就意味著我們的這個方法會一次性調(diào)用97次嗎???
答案是否定的, 其實, 我們的cell
的創(chuàng)建不是一次完成的, 我們可以在這個方法中試著打印 , 我們會發(fā)現(xiàn), 他會打印7次, 或者8次.
這是由于,蘋果官方在開發(fā)的時候, 為了性能的優(yōu)化, 有這樣的一個規(guī)律:
每當(dāng)有cell
進入我們的視野的時候, 新進來的cell
就會被創(chuàng)建. 但是, 如果cell
離開我們的視野之后, 再進入視野, 這個cell
又會被重新創(chuàng)建
這樣就會導(dǎo)致我們的性能的損耗
**2. ** 所以在這里我們就用到了, 新的知識:
-
cell
的循環(huán)利用
注意: 假設(shè),我們的手機屏幕只可以放下7個cell
那么當(dāng)我們將手機屏幕向下拖動的時候, 最多可以顯示8個cell
,當(dāng)我們繼續(xù)拖動的時候, 我們會發(fā)現(xiàn), 手機屏幕中的第一個cell
會離開我們的手機屏幕, 這個時候注意: 系統(tǒng)中TableView中會有一個緩存池, 而且這個緩存池系統(tǒng)會幫我們維護
, 專門存放我們的這個離開手機屏幕的cell
, 等到, 我們拖動到要顯示第9個cell
的時候, 我們可以判斷緩存池中是否有cell
, 如果有, 我們就直接拿過來, 并將以前的數(shù)據(jù)覆蓋掉. - 離開屏幕就到緩存池, 出現(xiàn)新的
cell
就先到緩存池找是否有cell
如果有就直接覆蓋數(shù)據(jù), 拿過來用. 如果沒有, 就創(chuàng)建一個新的cell
- 當(dāng)然, 以后我們的需要使用
TableView
中更加復(fù)雜的東西的時候, 我們的緩存池可能存放的不止一種cell
這個時候, 我們就需要在提前對我們的每一個cell
加一個標識, 方便以后查找
2. 步驟:
所以根據(jù)上的說的, 我們想要實現(xiàn)cell
循環(huán)使用需要以下三步:
- 通過一個標識去緩存池中尋找可循環(huán)利用的
cell
- 如果緩存池中找不到可循環(huán)的
cell
; 創(chuàng)建一個新的cell
并給其貼一個標識 - 給
cell
設(shè)置新的數(shù)據(jù)
3. 代碼重寫:
// 離開屏幕的cell會怎樣
/**
* 每當(dāng)有一個cell進入視野范圍內(nèi),就會調(diào)用
*/
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// static修飾局部變量:可以保證局部變量只分配一次存儲空間(只初始化一次)
static NSString *ID = @"hero";
// 1.通過一個標識去緩存池中尋找可循環(huán)利用的cell
// dequeue : 出列 (查找)
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 2.如果沒有可循環(huán)利用的cell
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
// 3.給cell設(shè)置新的數(shù)據(jù)
// 取出模型
MJHero *hero = self.heros[indexPath.row];
// 設(shè)置cell的數(shù)據(jù)
cell.textLabel.text = hero.name;
cell.detailTextLabel.text = hero.intro;
cell.imageView.image = [UIImage imageNamed:hero.icon];
return cell;
}
6. 多組汽車品牌展示:
效果展示:
1. 注意點
- 今天的多組數(shù)據(jù), 與以往不同.
先說plist文件的加載:
以往我們的plist文件的加載, 是只需要一個模型類. 今天做的這個程序是需要兩個模型類, 一個用來存儲: 汽車的數(shù)據(jù)
另一個使用來存儲汽車組的數(shù)據(jù)
在我們的這個知識點中, 其實只有一個: 那就是關(guān)于字典轉(zhuǎn)模型的更深一層的了解.
2. 知識點:
- 兩個模型類:
上面我們介紹到了, 一個模型類用來存儲汽車組數(shù)據(jù)的
, 因為我們的這次的plist文件要比以往復(fù)雜:
而且, 我們以前在數(shù)組轉(zhuǎn)模型的時候, 一行代碼便可, 現(xiàn)在不可以了
**以前的代碼: **
@implementation MJCar
+ (instancetype)carWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
@end
**現(xiàn)在的代碼: **
@implementation MJCarGroup
+ (instancetype)groupWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
// 賦值標題
self.title = dict[@"title"];
// 取出原來的字典數(shù)組
NSArray *dictArray = dict[@"cars"];
NSMutableArray *carArray = [NSMutableArray array];
for (NSDictionary *dict in dictArray) {
MJCar *car = [MJCar carWithDict:dict];
[carArray addObject:car];
}
self.cars = carArray;
}
return self;
}
@end
這是由于, 一開始的第一個模型轉(zhuǎn)數(shù)組的時候 , 它只是將他的title
轉(zhuǎn)成了模型, 而我們的car
雖然是個模型, 因為他里面還有數(shù)組并沒有轉(zhuǎn)成模型, 所以,我們需要創(chuàng)建兩個模型類
- 關(guān)于右邊的那個索引條
右邊的那個索引條是我們的數(shù)據(jù)源自帶的一個方法, 上面的字母是我們提前在plist文件中有的.
那個索引條上面的字母是我們隨意寫的, 而且, 他是按照從上到下的順序, 幫助我們進行快速查找, 假如說, 我們將A
與B
的位置互相調(diào)換一下之后, 當(dāng)我們點擊B
的時候, 他會向我們展示的是A
類的汽車
3. 代碼:
控制器.m文件
#import "MJViewController.h"
#import "MJCarGroup.h"
#import "MJCar.h"
@interface MJViewController ()<UITableViewDataSource>
/**
* 車品牌組數(shù)據(jù)
*/
@property (nonatomic, strong) NSArray *groups;
@end
@implementation MJViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (NSArray *)groups
{
if (_groups == nil) {
// 初始化
// 1.獲得plist的全路徑
NSString *path = [[NSBundle mainBundle] pathForResource:@"cars_total.plist" ofType:nil];
// 2.加載數(shù)組
NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
// 3.將dictArray里面的所有字典轉(zhuǎn)成模型對象,放到新的數(shù)組中
NSMutableArray *groupArray = [NSMutableArray array];
for (NSDictionary *dict in dictArray) {
// 3.1.創(chuàng)建模型對象
MJCarGroup *group = [MJCarGroup groupWithDict:dict];
// 3.2.添加模型對象到數(shù)組中
[groupArray addObject:group];
}
// 4.賦值
_groups = groupArray;
}
return _groups;
}
#pragma mark - 數(shù)據(jù)源方法
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.groups.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
MJCarGroup *group = self.groups[section];
return group.cars.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.定義一個循環(huán)標識
static NSString *ID = @"car";
// 2.從緩存池中取出可循環(huán)利用cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 3.緩存池中沒有可循環(huán)利用的cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
}
// 4.設(shè)置數(shù)據(jù)
MJCarGroup *group = self.groups[indexPath.section];
MJCar *car = group.cars[indexPath.row];
cell.imageView.image = [UIImage imageNamed:car.icon];
cell.textLabel.text = car.name;
return cell;
}
/**
* 第section組顯示的頭部標題
*/
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
MJCarGroup *group = self.groups[section];
return group.title;
}
/**
* 返回右邊索引條顯示的字符串?dāng)?shù)據(jù)
*/
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return [self.groups valueForKeyPath:@"title"];
}
// 這個是隱藏狀態(tài)欄
- (BOOL)prefersStatusBarHidden
{
return YES;
}
@end
CarGroup. h
#import <Foundation/Foundation.h>
@interface MJCarGroup : NSObject
/**
* 這組的標題
*/
@property (nonatomic, copy) NSString *title;
/**
* 存放的所有的汽車品牌(里面裝的都是MJCar模型)
*/
@property (nonatomic, strong) NSArray *cars;
+ (instancetype)groupWithDict:(NSDictionary *)dict;
- (instancetype)initWithDict:(NSDictionary *)dict;
@end
CarGroup. m
#import "MJCarGroup.h"
#import "MJCar.h"
@implementation MJCarGroup
+ (instancetype)groupWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
// 賦值標題
self.title = dict[@"title"];
// 取出原來的字典數(shù)組
NSArray *dictArray = dict[@"cars"];
NSMutableArray *carArray = [NSMutableArray array];
for (NSDictionary *dict in dictArray) {
MJCar *car = [MJCar carWithDict:dict];
[carArray addObject:car];
}
self.cars = carArray;
}
return self;
}
@end
Car.h
#import <Foundation/Foundation.h>
@interface MJCar : NSObject
/**
* 圖標
*/
@property (nonatomic, copy) NSString *icon;
/**
* 名稱
*/
@property (nonatomic, copy) NSString *name;
+ (instancetype)carWithDict:(NSDictionary *)dict;
- (instancetype)initWithDict:(NSDictionary *)dict;
@end
Car.m
#import "MJCar.h"
@implementation MJCar
+ (instancetype)carWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
@end
7. 數(shù)據(jù)刷新
**目的: **
上午我們講了一些關(guān)于汽車品牌的, 但是, 我們注意到那上面的數(shù)據(jù)都是死的, 不能修改, 所以今天我們就做這個刷新的功能
我們今天利用上次的英雄展示那個應(yīng)用 來完成今天的知識點. 效果就是:
當(dāng)我們點擊其中的一行的時候, 會彈出一個框, 然后里面課可以修改我們英雄的數(shù)據(jù)
1. 效果圖:
2. 步驟:
在我們的storyboard界面將我們的tableView連線. 和我們的控制器鏈接 ,然后, 再遵守我們的協(xié)議, 使之成為我們tatableView的代理
由于我們在后面同樣需要彈框(
AlerView
)這個效果, 而且要監(jiān)聽AlerView
內(nèi)部 確認或者取消按鈕的點擊, 所以同樣的我們需要遵守AlerView
的協(xié)議成為他的代理-
協(xié)議名稱:
<UITableViewDataSource, UITableViewDelegate, UIAlertViewDelegate>
1. tableView的代理
- 取得我們被點擊的模型
- 設(shè)置彈框
- 設(shè)置對話框的類型
- 取得唯一的那個文本框,顯示英雄的名稱
- 綁定行號到alertView上
綁定行號的作用是后面我們在修改數(shù)據(jù)模型的時候, 可以取得該行號, 當(dāng)然, 這個其實是我們的
AlerView
的獨有的渠道, 為了就是方便我們的方法之間傳遞參數(shù)
**代碼: **
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.取得被點擊這行對應(yīng)的模型
MJHero *hero = self.heros[indexPath.row];
// 彈框
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"數(shù)據(jù)展示" message:nil delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];
// 設(shè)置對話框的類型
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
// 取得唯一的那個文本框,顯示英雄的名稱
[alert textFieldAtIndex:0].text = hero.name;
[alert show];
// 綁定行號到alertView上
alert.tag = indexPath.row;
}
2.
/**
* 點擊了alertView上面的按鈕就會調(diào)用這個方法
*
* @param buttonIndex 按鈕的索引,從0開始
*/
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) return;
// 按鈕的索引肯定不是0
// 1.取得文本框最后的文字
NSString *name = [alertView textFieldAtIndex:0].text;
// 2.修改模型數(shù)據(jù)
int row = alertView.tag;
MJHero *hero = self.heros[row];
hero.name = name;
// 3.告訴tableView重新加載模型數(shù)據(jù)
// reloadData : tableView會向數(shù)據(jù)源重新請求數(shù)據(jù)
// 重新調(diào)用數(shù)據(jù)源的相應(yīng)方法取得數(shù)據(jù)
// 重新調(diào)用數(shù)據(jù)源的tableView:numberOfRowsInSection:獲得行數(shù)
// 重新調(diào)用數(shù)據(jù)源的tableView:cellForRowAtIndexPath:得知每一行顯示怎樣的cell
// 全部刷新
// [self.tableView reloadData];
// 局部刷新
NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:0];
[self.tableView reloadRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationBottom];
}
作者說:
這個是我現(xiàn)在學(xué)的所有的東西了, 現(xiàn)在我用的是Markdown
不用像以前一樣, 還要把筆記整理一遍
這樣做的好處就是更新的更加容易, 也快一點.
壞處就是可能我在做筆記的時候, 知識點比較散亂, 所以各位見諒哈!!!