iOS UITableView 與 UITableViewController實(shí)例詳解
很多應(yīng)用都會(huì)在界面中使用某種列表控件:用戶可以選中、刪除或重新排列列表中的項(xiàng)目。這些控件其實(shí)都是UITableView 對象,可以用來顯示一組對象,例如,用戶地址薄中的一組人名。
UITableView 對象雖然只能顯示一行數(shù)據(jù),但是沒有行數(shù)限制。
•編寫新的應(yīng)用程序 JXHomepwner 應(yīng)用
創(chuàng)建應(yīng)用,填寫基本信息
•UITableViewController
UITableView 是視圖。我們知道 模型-視圖-控制器(Model-View-Controller),他是我們必須遵守的一種設(shè)計(jì)模式。其含義是,應(yīng)用創(chuàng)建的任何一個(gè)對象,其類型必定是以下三種類型中的一種。
1. 模型:負(fù)責(zé)存儲(chǔ)數(shù)據(jù),與用戶界面無關(guān)。
2. 視圖:負(fù)責(zé)顯示界面,與模型對象無關(guān)。
3. 控制器:負(fù)責(zé)確保視圖對象和模型對象的數(shù)據(jù)保持一致。
一般來說,作為視圖對象的 UITableView 不應(yīng)該負(fù)責(zé)處理應(yīng)用的邏輯或數(shù)據(jù)。當(dāng)在應(yīng)用中使用 UITableView 對象的時(shí)候,必須考慮如何大啊呸其他的對象,與 UITableView 對象一起工作:
通常情況下,要通過某個(gè)視圖控制器對象來創(chuàng)建和釋放 UITableView 對象,并負(fù)責(zé)顯示或者隱藏視圖。
UITableView 對象要有數(shù)據(jù)源才能正常工作。UITableView 對象會(huì)向數(shù)據(jù)源查詢要顯示的行數(shù),顯示表格行所需要的數(shù)據(jù)和其他所需要的數(shù)據(jù)。沒有數(shù)據(jù)源的 UITableView 對象只是空殼。凡是遵守 UITableViewDataSource 協(xié)議的對象,都可以成為 UITableView 對象的數(shù)據(jù)源(即dataSource屬性所指向的對象)。
通常情況下,要為 UITableView 對象設(shè)置委托對象,以便能在該對象發(fā)生特定事件的時(shí)候做出相應(yīng)的處理。凡是遵守 UITableViewDelegate 協(xié)議的對象,都可以成為 UITableView 對象的委托對象。
UITableViewController 對象可以扮演以上全部角色,包括視圖控制器對象、數(shù)據(jù)源和委托對象。
UITableViewController 是 UIViewController 的子類,所以也有 view 屬性。UITableViewController 對象的 view 屬性指向一個(gè) UITableView 對象,并且這個(gè)對象由 UITableViewController 對象負(fù)責(zé)設(shè)置和顯示。UITableViewController 對象會(huì)在創(chuàng)建 UITableView 對象后,為這個(gè) UITableView 對象的 dataSource 和 delegate 賦值,并指向自己。
• 創(chuàng)建 UITableViewController 子類
下面要為我們創(chuàng)建的程序編寫一個(gè) UITableViewController 子類。
UITableViewController 的指定初始化方法是 initWithStyle: 調(diào)用 initWithStyle: 時(shí)要傳入一個(gè)類型作為 UITableViewStyle 的常熟,該常熟決定了 UITableView 對象的風(fēng)格。目前可以使用的 UITableViewStyle 常量有兩個(gè),即 UITableViewStylePlain 和 UITableViewStyleGrouped 。
現(xiàn)在將 UITableViewController 的指定初始化方法改為 init: ,為此時(shí)需要遵守兩條規(guī)則:
1. 在新的指定初始化方法中調(diào)用父類的指定初始化方法。
2. 覆蓋父類的初始化方法,調(diào)用新的指定初始化方法。
#import "JXItemsViewController.h" @interface JXItemsViewController () @end @implementation JXItemsViewController - (instancetype)init { // 調(diào)用父類的指定初始化方法 self = [super initWithStyle:UITableViewStylePlain]; return self; } - (instancetype)initWithStyle:(UITableViewStyle)style { return [self init]; } @end
實(shí)現(xiàn)以上兩個(gè)初始化方法之后,可以確保無論向新創(chuàng)建的 JXItemsViewController 對象發(fā)送哪一個(gè)初始化方法,初始化后的對象都會(huì)使用我們指定的風(fēng)格。
接下來代碼如下:
#import "AppDelegate.h" #import "JXItemsViewController.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; // 添加初始化代碼 // 創(chuàng)建 JXItemsViewController 對象 JXItemsViewController * itemsViewController = [[JXItemsViewController alloc] init]; // 將 JXItemsViewController 的標(biāo)示圖加入窗口 self.window.rootViewController = itemsViewController; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; }
構(gòu)建并運(yùn)行應(yīng)用我們確實(shí)能在屏幕上看到 UITableView 對象。JXItemsViewController 作為 UITableViewController 的子類,集成了 view 方法。 view 方法會(huì)調(diào)用 loadView 方法,如果視圖不存在,則 loadView 方法會(huì)創(chuàng)建并載入一個(gè)空的視圖。
下面我們要為 UITableView 設(shè)置內(nèi)容。
新建 JXItem 類
#import <Foundation/Foundation.h> @interface JXItem : NSObject /** 創(chuàng)建日期 */ @property (nonatomic,strong,readonly) NSDate * createDate; /** 名稱 */ @property (nonatomic,strong) NSString * itemName; /** 編號 */ @property (nonatomic,strong) NSString * serialnumber; /** 價(jià)值 */ @property (nonatomic,assign) NSInteger valueInDollars; /** JXImageStore中的鍵 */ @property (nonatomic,strong) NSString * itemKey; + (instancetype)randomItem; /** * JXItem類指定的初始化方法 * @return 類對象 */ - (instancetype)initWithItemName:(NSString *)name valueInDollars:(NSInteger)value serialNumber:(NSString *)sNumber; - (instancetype)initWithItemName:(NSString *)name; @end #import "JXItem.h" @implementation JXItem + (instancetype)randomItem { // 創(chuàng)建不可變數(shù)組對象,包含三個(gè)形容詞 NSArray * randomAdjectiveList = @[ @"Fluffy", @"Rusty", @"Shiny" ]; // 創(chuàng)建不可變數(shù)組對象,包含三個(gè)名詞 NSArray * randomNounList = @[ @"Bear", @"Spork", @"Mac" ]; // 根據(jù)數(shù)組對象所含的對象的個(gè)數(shù),得到隨機(jī)索引 // 注意:運(yùn)算符%是模運(yùn)算符,運(yùn)算后得到的是余數(shù) NSInteger adjectiveIndex = arc4random() % randomAdjectiveList.count; NSInteger nounIndex = arc4random() % randomNounList.count; // 注意,類型為NSInteger 的變量不是對象 NSString * randomName = [NSString stringWithFormat:@"%@ %@",randomAdjectiveList[adjectiveIndex],randomNounList[nounIndex]]; NSInteger randomValue = arc4random_uniform(100); NSString * randomSerialNumber = [NSString stringWithFormat:@"%c%c%c%c", '0' + arc4random_uniform(10), 'A' + arc4random_uniform(26), '0' + arc4random_uniform(10), 'A' + arc4random_uniform(26)]; JXItem * newItem = [[self alloc] initWithItemName:randomName valueInDollars:randomValue serialNumber:randomSerialNumber]; return newItem; } - (NSString *)description { NSString * descriptionString = [NSString stringWithFormat:@"%@ (%@):Worth $%zd, recorded on %@",self.itemName,self.serialnumber,self.valueInDollars,self.createDate]; return descriptionString; } - (instancetype)initWithItemName:(NSString *)name valueInDollars:(NSInteger)value serialNumber:(NSString *)sNumber { // 調(diào)用父類的指定初始化方法 self = [super init]; // 父類的指定初始化方法是否成功創(chuàng)建了對象 if (self) { // 為實(shí)例變量設(shè)置初始值 _itemName = name; _valueInDollars = value; _serialnumber = sNumber; // 設(shè)置_createDate為當(dāng)前時(shí)間 _createDate = [NSDate date]; // 創(chuàng)建一個(gè) NSUUID 對象 NSUUID * uuid = [[NSUUID alloc] init]; NSString * key = [uuid UUIDString]; _itemKey = key; } // 返回初始化后的對象的新地址 return self; } - (instancetype)initWithItemName:(NSString *)name { return [self initWithItemName:name valueInDollars:0 serialNumber:@""]; } - (instancetype)init { return [self initWithItemName:@"Item"]; } - (void)dealloc { NSLog(@"Destoryed:%@",self); } @end
•UITableView 數(shù)據(jù)源
創(chuàng)建JXItemStore
JXItemStore 對象是一個(gè)單例,也就是說,每個(gè)應(yīng)用只會(huì)有一個(gè)這種類型的對象。如果應(yīng)用嘗試創(chuàng)建另一個(gè)對象,JXItemStore類就會(huì)返回已經(jīng)存在的那個(gè)對象。當(dāng)某個(gè)程序要在很多不同的代碼段中使用同一個(gè)對象時(shí),將這個(gè)對象設(shè)置為單例是一種很好的設(shè)計(jì)模式,只需要向該對象的類發(fā)送特定的方法,就可以得到相同的對象。
#import <Foundation/Foundation.h> @interface JXItemStore : NSObject // 注意,這是一個(gè)類方法,前綴是+ + (instancetype)sharedStore; @end 在 JXItemStore 類收到 sharedStore 消息后,會(huì)檢查自己是否已經(jīng)創(chuàng)建 JXItemStore 的單例對象。如果已經(jīng)創(chuàng)建,就返回自己已經(jīng)創(chuàng)建的對象,否則就需要先創(chuàng)建,然后再返回。 #import "JXItemStore.h" @implementation JXItemStore // 單粒對象 + (instancetype)sharedStore { static JXItemStore * sharedStore = nil; // 判斷是否需要?jiǎng)?chuàng)建一個(gè) sharedStore 對象 if (!sharedStore) { sharedStore = [[self alloc] init]; } return sharedStore; } @end
這段代碼將 sharedStore 指針聲明了 靜態(tài)變量。當(dāng)某個(gè)定義了靜態(tài)變量的方法返回時(shí),程序不會(huì)釋放相應(yīng)的變量。靜態(tài)變量和全局變量一樣,并不是保存在棧中的。
sharedStore 變量的初始值為 nil。當(dāng)程序第一次執(zhí)行 sharedStore 方法時(shí),會(huì)創(chuàng)建一個(gè) JXItemStore 對象,并將新創(chuàng)建的對象的地址賦值給 sharedStore 變量。當(dāng)程序再次執(zhí)行 sharedStore 方法時(shí),不管是第幾次,其指針總是指向最初創(chuàng)建的那個(gè)對象。因?yàn)橹赶?JXItemStore 對象的 sharedStore 變量是強(qiáng)引用,且程序永遠(yuǎn)不會(huì)釋放該變量,所以 sharedStore 變量所指向的 JXItemStore 對象永遠(yuǎn)也不會(huì)被釋放。
JXItemsViewController 需要?jiǎng)?chuàng)建一個(gè)新的 JXItem 對象時(shí)會(huì)向 JXItemStore 對象發(fā)送消息,收到消息的 JXItemStore 對象會(huì)創(chuàng)建一個(gè) JXItem 對象并將其保存到一個(gè) JXItem 數(shù)組中,之后 JXItemsViewController 可以通過該數(shù)組獲取所有 JXItem 對象,并使用這些對象填充自己的表視圖。
#import <Foundation/Foundation.h> @class JXItem; @interface JXItemStore : NSObject /** 存放 JXItem 對象數(shù)組 */ @property (nonatomic,readonly) NSArray * allItem; // 注意,這是一個(gè)類方法,前綴是+ + (instancetype)sharedStore; - (JXItem *)createItem; @end
在實(shí)現(xiàn)文件中編輯。但是我們需要注意,在我們的應(yīng)用中將使用 JXItemStore 管理 JXItem 數(shù)組-包括添加、刪除和排序。因此,除 JXItemStore 之外的類不應(yīng)該對 JXItem 數(shù)組做這些操作。在 JXItemStore 內(nèi)部,需要將 JXItem 數(shù)組定義為可變數(shù)組。而對其他類來說,JXItem 數(shù)組則是不可變的數(shù)組。這是一種常見的設(shè)計(jì)模式,用于設(shè)置內(nèi)部數(shù)據(jù)的訪問權(quán)限:某個(gè)對象中有一種可修改的數(shù)據(jù),但是除該對象本身之外,其他對象只能訪問該數(shù)據(jù)而不能修改它。
#import "JXItemStore.h" #import "JXItem.h" @interface JXItemStore () /** 可變數(shù)組,用來操作 JXItem 對象 */ @property (nonatomic,strong) NSMutableArray * privateItems; @end @implementation JXItemStore // 單粒對象 + (instancetype)sharedStore { static JXItemStore * sharedStore = nil; // 判斷是否需要?jiǎng)?chuàng)建一個(gè) sharedStore 對象 if (!sharedStore) { sharedStore = [[self alloc] init]; } return sharedStore; } - (NSArray *)allItem { return self.privateItems; } #pragma mark - 懶加載 - (NSMutableArray *)privateItems{ if (_privateItems == nil) { _privateItems = [[NSMutableArray alloc] init]; } return _privateItems; } @end
allItem 方法的返回值是 NSArray 類型,但是方法體中返回的是 NSMutableArray 類型的對象,這種寫法是正確的,因?yàn)镹SMutableArray 是 NSArray 子類。
這種寫法可能會(huì)引起一個(gè)問題:雖然頭文件中將 allItem 的類型聲明為 NSArray ,但是其他對象調(diào)用 JXItemStore 的 allItem 方法時(shí),得到的一定是一個(gè) NSMutableArray 對象。
使用像 JXItemStore 這樣的類時(shí),應(yīng)該遵守其頭文件中的聲明使用類的屬性和方法。 例如,在 JXItemStore 頭文件中,因?yàn)?allItem 屬性的類型是 NSArray ,所以應(yīng)該將其作為 NASrray 類型的對象使用。如果將 allItem 轉(zhuǎn)換為 NSMutableArray 類型并修改其內(nèi)容,就違反了 JXItemStore 頭文件中的聲明??梢酝ㄟ^覆蓋 allItem 方法避免其他類修改 allItem 。
#import "JXItemStore.h" #import "JXItem.h" @interface JXItemStore () /** 可變數(shù)組,用來操作 JXItem 對象 */ @property (nonatomic,strong) NSMutableArray * privateItems; @end @implementation JXItemStore // 單粒對象 + (instancetype)sharedStore { static JXItemStore * sharedStore = nil; // 判斷是否需要?jiǎng)?chuàng)建一個(gè) sharedStore 對象 if (!sharedStore) { sharedStore = [[self alloc] init]; } return sharedStore; } - (NSArray *)allItem { return [self.privateItems copy]; } - (JXItem *)createItem { JXItem * item = [JXItem randomItem]; [self.privateItems addObject:item]; return item; } #pragma mark - 懶加載 - (NSMutableArray *)privateItems{ if (_privateItems == nil) { _privateItems = [[NSMutableArray alloc] init]; } return _privateItems; } @end
實(shí)現(xiàn)數(shù)據(jù)源方法
#import "JXItemsViewController.h" #import "JXItem.h" #import "JXItemStore.h" @interface JXItemsViewController () @end @implementation JXItemsViewController - (instancetype)init { // 調(diào)用父類的指定初始化方法 self = [super initWithStyle:UITableViewStylePlain]; if (self) { for (NSInteger i=0; i<5; i++) { [[JXItemStore sharedStore] createItem]; } } return self; } - (instancetype)initWithStyle:(UITableViewStyle)style { return [self init]; } @end
當(dāng)某個(gè) UITableView 對象要顯示表格內(nèi)容時(shí),會(huì)向自己的數(shù)據(jù)源(dataSource 屬性所指向的對象)發(fā)送一系列消息,其中包括必須方法和可選方法。
@required - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; // Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier: // Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls) - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; @optional - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; // Default is 1 if not implemented - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; // fixed font style. use custom view (UILabel) if you want something different - (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section; // Editing // Individual rows can opt out of having the -editing property set for them. If not implemented, all rows are assumed to be editable. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath; // Moving/reordering // Allows the reorder accessory view to optionally be shown for a particular row. By default, the reorder control will be shown only if the datasource implements -tableView:moveRowAtIndexPath:toIndexPath: - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath; // Index - (nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView __TVOS_PROHIBITED; // return list of section titles to display in section index view (e.g. "ABCD...Z#") - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index __TVOS_PROHIBITED; // tell table which section corresponds to section title/index (e.g. "B",1)) // Data manipulation - insert and delete support // After a row has the minus or plus button invoked (based on the UITableViewCellEditingStyle for the cell), the dataSource must commit the change // Not called for edit actions using UITableViewRowAction - the action's handler will be invoked instead - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath; // Data manipulation - reorder / moving support - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath; @end
實(shí)現(xiàn)行數(shù)代碼
#import "JXItemsViewController.h" #import "JXItem.h" #import "JXItemStore.h" @interface JXItemsViewController () @end @implementation JXItemsViewController - (instancetype)init { // 調(diào)用父類的指定初始化方法 self = [super initWithStyle:UITableViewStylePlain]; if (self) { for (NSInteger i=0; i<5; i++) { [[JXItemStore sharedStore] createItem]; } } return self; } - (instancetype)initWithStyle:(UITableViewStyle)style { return [self init]; } - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[[JXItemStore sharedStore] allItem] count]; } @end
UITableViewDataSource 協(xié)議中的另外一個(gè)必須實(shí)現(xiàn)的方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
在此之前,我們需要先了解另一個(gè)類:UITableViewCell
•UITableViewCell 對象
表視圖所顯示的每一行都是一個(gè)獨(dú)立的視圖,這些視圖是 UITableViewCell 對象。其對象還有一個(gè)子視圖:contentView 。contentView 也包含了很多子視圖,他的子視圖構(gòu)成 UITableViewCell 對象的主要外觀。此外, UITableViewCell 對象還可以顯示一個(gè)輔助指示圖。輔助指示視圖的作用是顯示一個(gè)指定的圖標(biāo),用于向用戶提示 UITableViewCell 對象可以執(zhí)行的動(dòng)作。這些圖標(biāo)包括勾起標(biāo)記、展開圖標(biāo)或中間有v形團(tuán)的藍(lán)色圓點(diǎn)。其默認(rèn)是 UITableViewCellAccessoryNone 。
在創(chuàng)建 UITableViewCell 對象時(shí),可以選擇不同的風(fēng)格來決定 UITableViewCell 對象顯示。
typedef NS_ENUM(NSInteger, UITableViewCellStyle) { UITableViewCellStyleDefault, // Simple cell with text label and optional image view (behavior of UITableViewCell in iPhoneOS 2.x) UITableViewCellStyleValue1, // Left aligned label on left and right aligned label on right with blue text (Used in Settings) UITableViewCellStyleValue2, // Right aligned label on left with blue text and left aligned label on right (Used in Phone/Contacts) UITableViewCellStyleSubtitle // Left aligned label on top and left aligned label on bottom with gray text (Used in iPod). }; // available in iPhone OS 3.0
創(chuàng)建并獲取 UITableViewCell 對象
下面我們主要對 tableView: cellForRowAtIndexPath: 方法進(jìn)行改寫。首先我們需要將 JXItem 數(shù)據(jù)跟 UITableViewCell 對象對應(yīng)起來。在方法中有一個(gè)實(shí)參是 NSIndexPath 對象,該對象包含兩個(gè)屬性 section(段) 和 row(行) 。當(dāng) UITableView 對象向其數(shù)據(jù)源發(fā)送 tableView: cellForRowAtIndexPath: 消息時(shí),其目的是獲取顯示第 section 個(gè)表格段、第 row 行數(shù)據(jù)的 UITableViewCell 對象。
#import "JXItemsViewController.h" #import "JXItem.h" #import "JXItemStore.h" @interface JXItemsViewController () @end @implementation JXItemsViewController - (instancetype)init { // 調(diào)用父類的指定初始化方法 self = [super initWithStyle:UITableViewStylePlain]; if (self) { for (NSInteger i=0; i<15; i++) { [[JXItemStore sharedStore] createItem]; } } return self; } - (instancetype)initWithStyle:(UITableViewStyle)style { return [self init]; } - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[[JXItemStore sharedStore] allItem] count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 創(chuàng)建 UITableViewCell 對象,風(fēng)格使用默認(rèn)風(fēng)格 UITableViewCell * cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UITableViewCell"]; // 獲取 allItem 的第 n 個(gè) JXItem 對象 // 然后將該 JXItem 對象的描述信息賦值給 UITableViewCell 對象的 textLabel // 這里的 n 是該 UITableViewCell 對象所對應(yīng)的表格索引 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; cell.textLabel.text = [item description]; return cell; } @end
構(gòu)建并運(yùn)行
重用UITableViewCell對象
iOS設(shè)備內(nèi)存是有限的,如果某個(gè) UITableView 對象要顯示大量的記錄,并且要針對每條記錄創(chuàng)建相應(yīng)的 UITableViewCell 對象,就會(huì)很快耗盡iOS設(shè)備內(nèi)存。
在 UITableView 上存在大量可優(yōu)化的地方,其中最重要的就是關(guān)于 UITableViewCell 復(fù)用問題。因?yàn)楫?dāng)我們滑動(dòng)界面是,大多數(shù)的 cell表格都會(huì)移出窗口,移出窗口的 UITableViewCell 對象放入 UITableViewCell 對象池,等待重用。當(dāng) UITableView 對象要求數(shù)據(jù)源返回某個(gè) UITableViewCell 對象時(shí),就可以先查看對象池。如果有未使用的 UITableViewCell 對象,就可以用新的數(shù)據(jù)配置這個(gè) UITableViewCell 對象,然后將其返回給 UITableView 對象,從而避免了創(chuàng)建新的對象,可以極大的優(yōu)化內(nèi)存。
但是這里還會(huì)有一個(gè)問題:如果我們在 UITableView 對象中創(chuàng)建了不同的 UITableViewCell 表格,用來展示不同的信息。那么這時(shí)候 UITableViewCell 對象池中的對象就會(huì)存在不同的類型,那么 UItableView 就有可能會(huì)得到錯(cuò)誤的類型的 UITableViewCell 對象。鑒于上述原因,必須保證 UITableView 對象能夠得到正確的指定類型的 UITableViewCell 對象,這樣才能確定返回的對象會(huì)擁有哪些屬性和方法。
從 UITableViewCell 對象池獲取對象時(shí),無需關(guān)心取回的是否是某個(gè)特性的對象,因?yàn)闊o論取回來的是哪個(gè)對象,都要重新設(shè)置數(shù)據(jù)。真正要關(guān)心的是取回來的對象是否是某個(gè)特性的類型。每個(gè) UITableViewCell 對象都有一個(gè)類型為 NSString 的 reuseIdentifier 屬性。當(dāng)數(shù)據(jù)源向 UITableView 對象獲取可重用的 UITableViewCell 對象時(shí),可傳入一個(gè)字符串并要求 UITableView 對象返回相應(yīng)的 UITableViewCell 對象。
#import "JXItemsViewController.h" #import "JXItem.h" #import "JXItemStore.h" @interface JXItemsViewController () @end @implementation JXItemsViewController - (instancetype)init { // 調(diào)用父類的指定初始化方法 self = [super initWithStyle:UITableViewStylePlain]; if (self) { for (NSInteger i=0; i<15; i++) { [[JXItemStore sharedStore] createItem]; } } return self; } - (instancetype)initWithStyle:(UITableViewStyle)style { return [self init]; } - (void)viewDidLoad { [super viewDidLoad]; // 向控制器注冊 [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[[JXItemStore sharedStore] allItem] count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 創(chuàng)建 UITableViewCell 對象,風(fēng)格使用默認(rèn)風(fēng)格 UITableViewCell * cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UITableViewCell"]; UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell" forIndexPath:indexPath]; // 獲取 allItem 的第 n 個(gè) JXItem 對象 // 然后將該 JXItem 對象的描述信息賦值給 UITableViewCell 對象的 textLabel // 這里的 n 是該 UITableViewCell 對象所對應(yīng)的表格索引 NSArray * items = [[JXItemStore sharedStore] allItem]; JXItem * item = items[indexPath.row]; cell.textLabel.text = [item description]; return cell; } @end
以上所述是小編給大家介紹的iOS UITableView 與 UITableViewController實(shí)例詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
- iOS應(yīng)用開發(fā)中UITableView的分割線的一些設(shè)置技巧
- 詳解iOS開發(fā)中UITableview cell 頂部空白的多種設(shè)置方法
- IOS UITableViewCell詳解及按鈕點(diǎn)擊事件處理實(shí)例
- 改變iOS應(yīng)用中UITableView的背景顏色與背景圖片的方法
- iOS App中UITableView左滑出現(xiàn)刪除按鈕及其cell的重用
- 全面解析iOS應(yīng)用中自定義UITableViewCell的方法
- 詳解iOS開發(fā)中UItableview控件的數(shù)據(jù)刷新功能的實(shí)現(xiàn)
- IOS 開發(fā)之UITableView 刪除表格單元寫法
相關(guān)文章
iOS開發(fā)存儲(chǔ)應(yīng)用程序Info.plist知識全面詳解
這篇文章主要為大家介紹了iOS開發(fā)存儲(chǔ)應(yīng)用程序Info.plist知識全面詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06IOS TextFiled與TextView 鍵盤的收起以及處理鍵盤遮擋
這篇文章主要介紹了IOS TextFiled與TextView 鍵盤的收起以及處理鍵盤遮擋的相關(guān)資料,需要的朋友可以參考下2016-12-12Android 在頁面中顯示打包日期的實(shí)現(xiàn)方法
下面小編就為大家分享一篇Android 在頁面中顯示打包日期的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01IOS使用UICollectionView實(shí)現(xiàn)無限輪播效果
這篇文章主要為大家詳細(xì)介紹了IOS使用UICollectionView實(shí)現(xiàn)無限輪播效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-03-03如何使用IOS自動(dòng)化測試工具UIAutomation
這篇文章主要介紹了UIAutomation使用實(shí)例、應(yīng)用技巧、基本知識點(diǎn)總結(jié)和需要注意事項(xiàng),具有一定的參考價(jià)值2021-04-04解析iOS開發(fā)中的FirstResponder第一響應(yīng)對象
這篇文章主要介紹了解析iOS開發(fā)中的FirstResponder第一響應(yīng)對象,包括View的FirstResponder的釋放問題,需要的朋友可以參考下2015-10-10