UITableView全面解析

来源:http://www.cnblogs.com/fume/archive/2016/03/17/5289314.html
-Advertisement-
Play Games

本文轉自:http://www.cocoachina.com/ios/20140922/9710.html 在iOS開發中UITableView可以說是使用最廣泛的控制項,我們平時使用的軟體中到處都可以看到它的影子,類似於微信、QQ、新浪微博等軟體基本上隨處都是UITableView。當然它的廣泛使用


 

本文轉自:http://www.cocoachina.com/ios/20140922/9710.html

 

 

在iOS開發中UITableView可以說是使用最廣泛的控制項,我們平時使用的軟體中到處都可以看到它的影子,類似於微信、QQ、新浪微博等軟體基本上隨處都是UITableView。當然它的廣泛使用自然離不開它強大的功能,今天這篇文章將針對UITableView重點展開討論。今天的主要內容包括:

1.基本介紹 2.數據源 3.代理 4.性能優化 5.UITableViewCell 6.常用操作 7.UITableViewController 8.MVC模式   基本介紹 UITableView有兩種風格:UITableViewStylePlain和UITableViewStyleGrouped。這兩者操作起來其實並沒有本質區別,只是後者按分組樣式顯示前者按照普通樣式顯示而已。大家先看一下兩者的應用:   1>分組樣式 2>不分組樣式   大家可以看到在UITableView中數據只有行的概念,並沒有列的概念,因為在手機操作系統中顯示多列是不利於操作的。UITableView中每行數據都是一個UITableViewCell,在這個控制項中為了顯示更多的信息,iOS已經在其內部設置好了多個子控制項以供開發者使用。如果我們查看UITableViewCell的聲明文件可以發現在內部有一個UIView控制項(contentView,作為其他元素的父控制項)、兩個UILable控制項(textLabel、detailTextLabel)、一個UIImage控制項(imageView),分別用於容器、顯示內容、詳情和圖片。使用效果類似於微信、QQ信息列表: 當然,這些子控制項並不一定要全部使用,具體操作時可以通過UITableViewCellStyle進行設置,具體每個枚舉表示的意思已經在代碼中進行了註釋:
  1. typedef NS_ENUM(NSInteger, UITableViewCellStyle) { 
  2.     UITableViewCellStyleDefault,    // 左側顯示textLabel(不顯示detailTextLabel),imageView可選(顯示在最左邊) 
  3.     UITableViewCellStyleValue1,        // 左側顯示textLabel、右側顯示detailTextLabel(預設藍色),imageView可選(顯示在最左邊) 
  4.     UITableViewCellStyleValue2,        // 左側依次顯示textLabel(預設藍色)和detailTextLabel,imageView可選(顯示在最左邊) 
  5.     UITableViewCellStyleSubtitle    // 左上方顯示textLabel,左下方顯示detailTextLabel(預設灰色),imageView可選(顯示在最左邊) 
  6. }; 
數據源 由於iOS是遵循MVC模式設計的,很多操作都是通過代理和外界溝通的,但對於數據源控制項除了代理還有一個數據源屬性,通過它和外界進行數據交互。 對於UITableView設置完dataSource後需要實現UITableViewDataSource協議,在這個協議中定義了多種 數據操作方法,下麵通過創建一個簡單的聯繫人管理進行演示: 首先我們需要創建一個聯繫人模型KCContact KCContact.h
  1. // 
  2. //  Contact.h 
  3. //  UITableView 
  4. // 
  5. //  Created by Kenshin Cui on 14-3-1. 
  6. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. 
  7. // 
  8.  
  9. #import  
  10.  
  11. @interface KCContact : NSObject 
  12.  
  13. #pragma mark 姓 
  14. @property (nonatomic,copy) NSString *firstName; 
  15. #pragma mark 名 
  16. @property (nonatomic,copy) NSString *lastName; 
  17. #pragma mark 手機號碼 
  18. @property (nonatomic,copy) NSString *phoneNumber; 
  19.  
  20. #pragma mark 帶參數的構造函數 
  21. -(KCContact *)initWithFirstName:(NSString *)firstName andLastName:(NSString *)lastName andPhoneNumber:(NSString *)phoneNumber; 
  22.  
  23. #pragma mark 取得姓名 
  24. -(NSString *)getName; 
  25.  
  26.  
  27. #pragma mark 帶參數的靜態對象初始化方法 
  28. +(KCContact *)initWithFirstName:(NSString *)firstName andLastName:(NSString *)lastName andPhoneNumber:(NSString *)phoneNumber; 
  29. @end 
KCContact.m
  1. // 
  2. //  Contact.m 
  3. //  UITableView 
  4. // 
  5. //  Created by Kenshin Cui on 14-3-1. 
  6. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. 
  7. // 
  8.  
  9. #import "KCContact.h" 
  10.  
  11. @implementation KCContact 
  12.  
  13. -(KCContact *)initWithFirstName:(NSString *)firstName andLastName:(NSString *)lastName andPhoneNumber:(NSString *)phoneNumber{ 
  14.     if(self=[super init]){ 
  15.         self.firstName=firstName; 
  16.         self.lastName=lastName; 
  17.         self.phoneNumber=phoneNumber; 
  18.     } 
  19.     return self; 
  20.  
  21. -(NSString *)getName{ 
  22.     return [NSString stringWithFormat:@"%@ %@",_lastName,_firstName]; 
  23.  
  24. +(KCContact *)initWithFirstName:(NSString *)firstName andLastName:(NSString *)lastName andPhoneNumber:(NSString *)phoneNumber{ 
  25.     KCContact *contact1=[[KCContact alloc]initWithFirstName:firstName andLastName:lastName andPhoneNumber:phoneNumber]; 
  26.     return contact1; 
  27.  
  28. @end 
為了演示分組顯示我們不妨將一組數據也抽象成模型KCContactGroup KCContactGroup.h
  1. // 
  2. //  KCContactGroup.h 
  3. //  UITableView 
  4. // 
  5. //  Created by Kenshin Cui on 14-3-1. 
  6. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. 
  7. // 
  8.  
  9. #import  
  10. #import "KCContact.h" 
  11.  
  12. @interface KCContactGroup : NSObject 
  13.  
  14. #pragma mark 組名 
  15. @property (nonatomic,copy) NSString *name; 
  16.  
  17. #pragma mark 分組描述 
  18. @property (nonatomic,copy) NSString *detail; 
  19.  
  20. #pragma mark 聯繫人 
  21. @property (nonatomic,strong) NSMutableArray *contacts; 
  22.  
  23. #pragma mark 帶參數個構造函數 
  24. -(KCContactGroup *)initWithName:(NSString *)name andDetail:(NSString *)detail andContacts:(NSMutableArray *)contacts; 
  25.  
  26. #pragma mark 靜態初始化方法 
  27. +(KCContactGroup *)initWithName:(NSString *)name andDetail:(NSString *)detail andContacts:(NSMutableArray *)contacts; 
  28.  
  29. @end 
KCContactGroup.m
  1. // 
  2. //  KCContactGroup.m 
  3. //  UITableView 
  4. // 
  5. //  Created by Kenshin Cui on 14-3-1. 
  6. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. 
  7. // 
  8.  
  9. #import "KCContactGroup.h" 
  10.  
  11. @implementation KCContactGroup 
  12.  
  13.  
  14. -(KCContactGroup *)initWithName:(NSString *)name andDetail:(NSString *)detail andContacts:(NSMutableArray *)contacts{ 
  15.     if (self=[super init]) { 
  16.         self.name=name; 
  17.         self.detail=detail; 
  18.         self.contacts=contacts; 
  19.     } 
  20.     return self; 
  21.  
  22. +(KCContactGroup *)initWithName:(NSString *)name andDetail:(NSString *)detail andContacts:(NSMutableArray *)contacts{ 
  23.     KCContactGroup *group1=[[KCContactGroup alloc]initWithName:name andDetail:detail andContacts:contacts]; 
  24.     return group1; 
  25. @end 
然後在viewDidLoad方法中創建一些模擬數據同時實現數據源協議方法: KCMainViewController.m
  1. // 
  2. //  KCMainViewController.m 
  3. //  UITableView 
  4. // 
  5. //  Created by Kenshin Cui on 14-3-1. 
  6. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. 
  7. // 
  8.  
  9. #import "KCMainViewController.h" 
  10. #import "KCContact.h" 
  11. #import "KCContactGroup.h" 
  12.  
  13. @interface KCMainViewController (){ 
  14.     UITableView *_tableView; 
  15.     NSMutableArray *_contacts;//聯繫人模型 
  16.  
  17. @end 
  18.  
  19. @implementation KCMainViewController 
  20.  
  21. - (void)viewDidLoad { 
  22.     [super viewDidLoad]; 
  23.      
  24.     //初始化數據 
  25.     [self initData]; 
  26.      
  27.     //創建一個分組樣式的UITableView 
  28.     _tableView=[[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; 
  29.      
  30.     //設置數據源,註意必須實現對應的UITableViewDataSource協議 
  31.     _tableView.dataSource=self; 
  32.      
  33.     [self.view addSubview:_tableView]; 
  34.  
  35. #pragma mark 載入數據 
  36. -(void)initData{ 
  37.     _contacts=[[NSMutableArray alloc]init]; 
  38.      
  39.     KCContact *contact1=[KCContact initWithFirstName:@"Cui" andLastName:@"Kenshin" andPhoneNumber:@"18500131234"]; 
  40.     KCContact *contact2=[KCContact initWithFirstName:@"Cui" andLastName:@"Tom" andPhoneNumber:@"18500131237"]; 
  41.     KCContactGroup *group1=[KCContactGroup initWithName:@"C" andDetail:@"With names beginning with C" andContacts:[NSMutableArray arrayWithObjects:contact1,contact2, nil]]; 
  42.     [_contacts addObject:group1]; 
  43.      
  44.  
  45.      
  46.     KCContact *contact3=[KCContact initWithFirstName:@"Lee" andLastName:@"Terry" andPhoneNumber:@"18500131238"]; 
  47.     KCContact *contact4=[KCContact initWithFirstName:@"Lee" andLastName:@"Jack" andPhoneNumber:@"18500131239"]; 
  48.     KCContact *contact5=[KCContact initWithFirstName:@"Lee" andLastName:@"Rose" andPhoneNumber:@"18500131240"]; 
  49.     KCContactGroup *group2=[KCContactGroup initWithName:@"L" andDetail:@"With names beginning with L" andContacts:[NSMutableArray arrayWithObjects:contact3,contact4,contact5, nil]]; 
  50.     [_contacts addObject:group2]; 
  51.      
  52.      
  53.      
  54.     KCContact *contact6=[KCContact initWithFirstName:@"Sun" andLastName:@"Kaoru" andPhoneNumber:@"18500131235"]; 
  55.     KCContact *contact7=[KCContact initWithFirstName:@"Sun" andLastName:@"Rosa" andPhoneNumber:@"18500131236"]; 
  56.  
  57.     KCContactGroup *group3=[KCContactGroup initWithName:@"S" andDetail:@"With names beginning with S" andContacts:[NSMutableArray arrayWithObjects:contact6,contact7, nil]]; 
  58.     [_contacts addObject:group3]; 
  59.      
  60.      
  61.     KCContact *contact8=[KCContact initWithFirstName:@"Wang" andLastName:@"Stephone" andPhoneNumber:@"18500131241"]; 
  62.     KCContact *contact9=[KCContact initWithFirstName:@"Wang" andLastName:@"Lucy" andPhoneNumber:@"18500131242"]; 
  63.     KCContact *contact10=[KCContact initWithFirstName:@"Wang" andLastName:@"Lily" andPhoneNumber:@"18500131243"]; 
  64.     KCContact *contact11=[KCContact initWithFirstName:@"Wang" andLastName:@"Emily" andPhoneNumber:@"18500131244"]; 
  65.     KCContact *contact12=[KCContact initWithFirstName:@"Wang" andLastName:@"Andy" andPhoneNumber:@"18500131245"]; 
  66.     KCContactGroup *group4=[KCContactGroup initWithName:@"W" andDetail:@"With names beginning with W" andContacts:[NSMutableArray arrayWithObjects:contact8,contact9,contact10,contact11,contact12, nil]]; 
  67.     [_contacts addObject:group4]; 
  68.      
  69.      
  70.     KCContact *contact13=[KCContact initWithFirstName:@"Zhang" andLastName:@"Joy" andPhoneNumber:@"18500131246"]; 
  71.     KCContact *contact14=[KCContact initWithFirstName:@"Zhang" andLastName:@"Vivan" andPhoneNumber:@"18500131247"]; 
  72.     KCContact *contact15=[KCContact initWithFirstName:@"Zhang" andLastName:@"Joyse" andPhoneNumber:@"18500131248"]; 
  73.     KCContactGroup *group5=[KCContactGroup initWithName:@"Z" andDetail:@"With names beginning with Z" andContacts:[NSMutableArray arrayWithObjects:contact13,contact14,contact15, nil]]; 
  74.     [_contacts addObject:group5]; 
  75.  
  76.  
  77. #pragma mark - 數據源方法 
  78. #pragma mark 返回分組數 
  79. -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ 
  80.     NSLog(@"計算分組數"); 
  81.     return _contacts.count; 
  82.  
  83. #pragma mark 返回每組行數 
  84. -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 
  85.     NSLog(@"計算每組(組%i)行數",section); 
  86.     KCContactGroup *group1=_contacts[section]; 
  87.     return group1.contacts.count; 
  88.  
  89. #pragma mark返回每行的單元格 
  90. -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 
  91.     //NSIndexPath是一個結構體,記錄了組和行信息 
  92.     NSLog(@"生成單元格(組:%i,行%i)",indexPath.section,indexPath.row); 
  93.     KCContactGroup *group=_contacts[indexPath.section]; 
  94.     KCContact *contact=group.contacts[indexPath.row]; 
  95.     UITableViewCell *cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; 
  96.     cell.textLabel.text=[contact getName]; 
  97.     cell.detailTextLabel.text=contact.phoneNumber; 
  98.     return cell; 
  99.  
  100. #pragma mark 返回每組頭標題名稱 
  101. -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ 
  102.     NSLog(@"生成組(組%i)名稱",section); 
  103.     KCContactGroup *group=_contacts[section]; 
  104.     return group.name; 
  105.  
  106. #pragma mark 返回每組尾部說明 
  107. -(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{ 
  108.     NSLog(@"生成尾部(組%i)詳情",section); 
  109.     KCContactGroup *group=_contacts[section]; 
  110.     return group.detail; 
  111. @end 
運行可以看到如下效果: 大家在使用iPhone通訊錄時會發現右側可以按字母檢索,使用起來很方便,其實這個功能使用UITableView實現很簡單,只要實現數據源協議的一個方法,構建一個分組標題的數組即可實現。數組元素的內容和組標題內容未必完全一致,UITableView是按照數組元素的索引和每組數據索引順序來定位的而不是按內容查找。
  1. #pragma mark 返回每組標題索引 
  2. -(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{ 
  3.     NSLog(@"生成組索引"); 
  4.     NSMutableArray *indexs=[[NSMutableArray alloc]init]; 
  5.     for(KCContactGroup *group in _contacts){ 
  6.         [indexs addObject:group.name]; 
  7.     } 
  8.     return indexs; 
效果如下: 需要註意的是上面幾個重點方法的執行順序,請看下圖: 值得指出的是生成單元格的方法並不是一次全部調用,而是只會生產當前顯示在界面上的單元格,當用戶滾動操作時再顯示其他單元格。   註意:隨著我們的應用越來越複雜,可能經常需要調試程式,在iOS中預設情況下不能定位到錯誤代碼行,我們可以通過如下設置讓程式定位到出錯代碼行:Show the Breakpoint  navigator—Add Exception breakpoint。   代理 上面我們已經看到通訊錄的簡單實現,但是我們發現單元格高度、分組標題高度以及尾部說明的高度都需要調整,此時就需要使用代理方法。UITableView代理方法有很多,例如監聽單元格顯示周期、監聽單元格選擇編輯操作、設置是否高亮顯示單元格、設置行高等。 1.設置行高
  1. #pragma mark - 代理方法 
  2. #pragma mark 設置分組標題內容高度 
  3. -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ 
  4.     if(section==0){ 
  5.         return 50; 
  6.     } 
  7.     return 40; 
  8.  
  9. #pragma mark 設置每行高度(每行高度可以不一樣) 
  10. -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 
  11.     return 45; 
  12.  
  13. #pragma mark 設置尾部說明內容高度 
  14. -(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{ 
  15.     return 40; 
2.監聽點擊 在iOS中點擊某聯繫個人就可以呼叫這個聯繫人,這時就需要監聽點擊操作,這裡就不演示呼叫聯繫人操作了,我們演示一下修改人員信息的操作。 KCMainViewContrller.m
  1. // 
  2. //  KCMainViewController.m 
  3. //  UITableView 
  4. // 
  5. //  Created by Kenshin Cui on 14-3-1. 
  6. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. 
  7. // 
  8.  
  9. #import "KCMainViewController.h" 
  10. #import "KCContact.h" 
  11. #import "KCContactGroup.h" 
  12.  
  13. @interface KCMainViewController ()<uitableviewdatasource,uitableviewdelegate,uialertviewdelegate>{ 
  14.     UITableView *_tableView; 
  15.     NSMutableArray *_contacts;//聯繫人模型 
  16.     NSIndexPath *_selectedIndexPath;//當前選中的組和行 
  17.  
  18. @end 
  19.  
  20. @implementation KCMainViewController 
  21.  
  22. - (void)viewDidLoad { 
  23.     [super viewDidLoad]; 
  24.      
  25.     //初始化數據 
  26.     [self initData]; 
  27.      
  28.     //創建一個分組樣式的UITableView 
  29.     _tableView=[[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; 
  30.      
  31.     //設置數據源,註意必須實現對應的UITableViewDataSource協議 
  32.     _tableView.dataSource=self; 
  33.     //設置代理 
  34.     _tableView.delegate=self; 
  35.      
  36.     [self.view addSubview:_tableView]; 
  37.  
  38. #pragma mark 載入數據 
  39. -(void)initData{ 
  40.     _contacts=[[NSMutableArray alloc]init]; 
  41.      
  42.     KCContact *contact1=[KCContact initWithFirstName:@"Cui" andLastName:@"Kenshin" andPhoneNumber:@"18500131234"]; 
  43.     KCContact *contact2=[KCContact initWithFirstName:@"Cui" andLastName:@"Tom" andPhoneNumber:@"18500131237"]; 
  44.     KCContactGroup *group1=[KCContactGroup initWithName:@"C" andDetail:@"With names beginning with C" andContacts:[NSMutableArray arrayWithObjects:contact1,contact2, nil]]; 
  45.     [_contacts addObject:group1]; 
  46.      
  47.  
  48.      
  49.     KCContact *contact3=[KCContact initWithFirstName:@"Lee" andLastName:@"Terry" andPhoneNumber:@"18500131238"]; 
  50.     KCContact *contact4=[KCContact initWithFirstName:@"Lee" andLastName:@"Jack" andPhoneNumber:@"18500131239"]; 
  51.     KCContact *contact5=[KCContact initWithFirstName:@"Lee" andLastName:@"Rose" andPhoneNumber:@"18500131240"]; 
  52.     KCContactGroup *group2=[KCContactGroup initWithName:@"L" andDetail:@"With names beginning with L" andContacts:[NSMutableArray arrayWithObjects:contact3,contact4,contact5, nil]]; 
  53.     [_contacts addObject:group2]; 
  54.      
  55.      
  56.      
  57.     KCContact *contact6=[KCContact initWithFirstName:@"Sun" andLastName:@"Kaoru" andPhoneNumber:@"18500131235"]; 
  58.     KCContact *contact7=[KCContact initWithFirstName:@"Sun" andLastName:@"Rosa" andPhoneNumber:@"18500131236"]; 
  59.  
  60.     KCContactGroup *group3=[KCContactGroup initWithName:@"S" andDetail:@"With names beginning with S" andContacts:[NSMutableArray arrayWithObjects:contact6,contact7, nil]]; 
  61.     [_contacts addObject:group3]; 
  62.      
  63.      
  64.     KCContact *contact8=[KCContact initWithFirstName:@"Wang" andLastName:@"Stephone" andPhoneNumber:@"18500131241"]; 
  65.     KCContact *contact9=[KCContact initWithFirstName:@"Wang" andLastName:@"Lucy" andPhoneNumber:@"18500131242"]; 
  66.     KCContact *contact10=[KCContact initWithFirstName:@"Wang" andLastName:@"Lily" andPhoneNumber:@"18500131243"]; 
  67.     KCContact *contact11=[KCContact initWithFirstName:@"Wang" andLastName:@"Emily" andPhoneNumber:@"18500131244"]; 
  68.     KCContact *contact12=[KCContact initWithFirstName:@"Wang" andLastName:@"Andy" andPhoneNumber:@"18500131245"]; 
  69.     KCContactGroup *group4=[KCContactGroup initWithName:@"W" andDetail:@"With names beginning with W" andContacts:[NSMutableArray arrayWithObjects:contact8,contact9,contact10,contact11,contact12, nil]]; 
  70.     [_contacts addObject:group4]; 
  71.      
  72.      
  73.     KCContact *contact13=[KCContact initWithFirstName:@"Zhang" andLastName:@"Joy" andPhoneNumber:@"18500131246"]; 
  74.     KCContact *contact14=[KCContact initWithFirstName:@"Zhang" andLastName:@"Vivan" andPhoneNumber:@"18500131247"]; 
  75.     KCContact *contact15=[KCContact initWithFirstName:@"Zhang" andLastName:@"Joyse" andPhoneNumber:@"18500131248"]; 
  76.     KCContactGroup *group5=[KCContactGroup initWithName:@"Z" andDetail:@"With names beginning with Z" andContacts:[NSMutableArray arrayWithObjects:contact13,contact14,contact15, nil]]; 
  77.     [_contacts addObject:group5]; 
  78.  
  79.  
  80. #pragma mark - 數據源方法 
  81. #pragma mark 返回分組數 
  82. -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ 
  83.     NSLog(@"計算分組數"); 
  84.     return _contacts.count; 
  85.  
  86. #pragma mark 返回每組行數 
  87. -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 
  88.     NSLog(@"計算每組(組%i)行數",section); 
  89.     KCContactGroup *group1=_contacts[section]; 
  90.     return group1.contacts.count; 
  91.  
  92. #pragma mark返回每行的單元格 
  93. -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 
  94.     //NSIndexPath是一個對象,記錄了組和行信息 
  95.     NSLog(@"生成單元格(組:%i,行%i)",indexPath.section,indexPath.row); 
  96.     KCContactGroup *group=_contacts[indexPath.section]; 
  97.     KCContact *contact=group.contacts[indexPath.row]; 
  98.     UITableViewCell *cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil]; 
  99.     cell.textLabel.text=[contact getName]; 
  100.     cell.detailTextLabel.text=contact.phoneNumber; 
  101.     return cell; 
  102.  
  103. #pragma mark 返回每組頭標題名稱 
  104. -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ 
  105.     NSLog(@"生成組(組%i)名稱",section); 
  106.     KCContactGroup *group=_contacts[section]; 
  107.     return group.name; 
  108.  
  109. #pragma mark 返回每組尾部說明 
  110. -(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{ 
  111.     NSLog(@"生成尾部(組%i)詳情",section); 
  112.     KCContactGroup *group=_contacts[section]; 
  113.     return group.detail; 
  114.  
  115. #pragma mark 返回每組標題索引 
  116. -(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{ 
  117.     NSLog(@"生成組索引"); 
  118.     NSMutableArray *indexs=[[NSMutableArray alloc]init]; 
  119.     for(KCContactGroup *group in _contacts){ 
  120.         [indexs addObject:group.name]; 
  121.     } 
  122.     return indexs; 
  123.  
  124. #pragma mark - 代理方法 
  125. #pragma mark 設置分組標題內容高度 
  126. -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ 
  127.     if(section==0){ 
  128.         return 50; 
  129.     } 
  130.     return 40; 
  131.  
  132. #pragma mark 設置每行高度(每行高度可以不一樣) 
  133. -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 
  134.     return 45; 
  135.  
  136. #pragma mark 設置尾部說明內容高度 
  137. -(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{ 
  138.     return 40; 
  139.  
  140. #pragma mark 點擊行 
  141. -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 
  142.     _selectedIndexPath=indexPath; 
  143.     KCContactGroup *group=_contacts[indexPath.section]; 
  144.     KCContact *contact=group.contacts[indexPath.row]; 
  145.     //創建彈出視窗 
  146.     UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"System Info" message:[contact getName] delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil]; 
  147.     alert.alertViewStyle=UIAlertViewStylePlainTextInput; //設置視窗內容樣式 
  148.     UITextField *textField= [alert textFieldAtIndex:0]; //取得文本框 
  149.     textField.text=contact.phoneNumber; //設置文本框內容 
  150.     [alert show]; //顯示視窗 
  151.  
  152. #pragma mark 視窗的代理方法,用戶保存數據 
  153. -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ 
  154.     //當點擊了第二個按鈕(OK) 
  155.     if (buttonIndex==1) { 
  156.         UITextField *textField= [alertView textFieldAtIndex:0]; 
  157.         //修改模型數據 
  158.         KCContactGroup *group=_contacts[_selectedIndexPath.section]; 
  159.         KCContact *contact=group.contacts[_selectedIndexPath.row]; 
  160.         contact.phoneNumber=textField.text; 
  161.         //刷新表格 
  162.         [_tableView reloadData]; 
  163.     } 
  164.  
  165. #pragma mark 重寫狀態樣式方法 
  166. -(UIStatusBarStyle)preferredStatusBarStyle{ 
  167.     return UIStatusBarStyleLightContent; 
  168. @end 
在上面的代碼中我們通過修改模型來改變UI顯示,這種方式是經典的MVC應用,在後面的代碼中會經常看到。當然UI的刷新使用了UITableView的reloadData方法,該方法會重新調用數據源方法,包括計算分組、計算每個分組的行數,生成單元格等刷新整個UITableView。當然這種方式在實際開發中是不可取的,我們不可能因為修改了一個人的信息就刷新整個UITableViewView,此時我們需要採用局部刷新。局部刷新使用起來很簡單,只需要調用UITableView的另外一個方法:
  1. #pragma mark 視窗的代理方法,用戶保存數據 
  2. -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ 
  3.     //當點擊了第二個按鈕(OK) 
  4.     if (buttonIndex==1) { 
  5.         UITextField *textField= [alertView textFieldAtIndex:0]; 
  6.         //修改模型數據 
  7.         KCContactGroup *group=_contacts[_selectedIndexPath.section]; 
  8.         KCContact *contact=group.contacts[_selectedIndexPath.row]; 
  9.         contact.phoneNumber=textField.text; 
  10.         //刷新表格 
  11.         NSArray *indexPaths=@[_selectedIndexPath];//需要局部刷新的單元格的組、行 
  12.         [_tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationLeft];//後面的參數代表更新時的動畫 
  13.     } 
性能優化 前面已經說過UITableView中的單元格cell是在顯示到用戶可視區域後創建的,那麼如果用戶往下滾動就會繼續創建顯示在屏幕上的單元格,如果用戶向上滾動返回到查看過的內容時同樣會重新創建之前已經創建過的單元格。如此一來即使UITableView的內容不是太多,如果用戶反覆的上下滾動,記憶體也會瞬間飆升,更何況很多時候UITableView的內容是很多的(例如微博展示列表,基本向下滾動是沒有底限的)。   前面一節中我們曾經提到過如何優化UIScrollView,當時就是利用有限的UIImageView動態切換其內容來儘可能減少資源占用。同樣的,在UITableView中也可以採用類似的方式,只是這時我們不是在滾動到指定位置後更改滾動的位置而是要將當前沒有顯示的Cell重新顯示在將要顯示的Cell的位置然後更新其內容。原因就是UITableView中的Cell結構佈局可能是不同的,通過重新定位是不可取的,而是需要重用已經不再界面顯示的已創建過的Cell。   當然,聽起來這麼做比較複雜,其實實現起來很簡單,因為UITableView已經為我們實現了這種機制。在UITableView內部有一個緩存池,初始化時使用initWithStyle:(UITableViewCellStyle) reuseIdentifier:(NSString *)方法指定一個可重用標識,就可以將這個cell放到緩存池。然後在使用時使用指定的標識去緩存池中取得對應的cell然後修改cell內容即可。   上面的代碼中已經列印了cell的地址,如果大家運行測試上下滾動UITableView會發現滾動時創建的cell地址是初始化時已經創建的。   這裡再次給大家強調兩點: 1. -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)方法調用很頻繁,無論是初始化、上下滾動、刷新都會調用此方法,所有在這裡執行的操作一定要註意性能; 2. 可重用標識可以有多個,如果在UITableView中有多類結構不同的Cell,可以通過這個標識進行緩存和重新。   UITableViewCell 1.自帶的UITableViewCell UITableViewCell是構建一個UITableView的基礎,在UITableViewCell內部有一個UIView控制項作為其他內容的容器,它上面有一個UIImageView和兩個UILabel,通過UITableViewCellStyle屬性可以對其樣式進行控制。其結構如下: 有時候我們會發現很多UITableViewCell右側可以顯示不同的圖標,在iOS中稱之為訪問器,點擊可以觸發不同的事件,例如設置功能: 要設置這些圖標只需要設置UITableViewCell的accesoryType屬性,這是一個枚舉類型具體含義如下:
  1. typedef NS_ENUM(NSInteger, UITableViewCellAccessoryType) { 
  2.     UITableViewCellAccessoryNone,                   // 不顯示任何圖標 
  3.     UITableViewCellAccessoryDisclosureIndicator,    // 跳轉指示圖標 
  4.     UITableViewCellAccessoryDetailDisclosureButton, // 內容詳情圖標和跳轉指示圖標 
  5.     UITableViewCellAccessoryCheckmark,              // 勾選圖標 
  6.     UITableViewCellAccessoryDetailButton NS_ENUM_AVAILABLE_IOS(7_0) // 內容詳情圖標 
  7. }; 
例如在最近通話中我們通常設置為詳情圖標,點擊可以查看聯繫人詳情: 很明顯iOS設置中第一個accessoryType不在枚舉之列,右側的訪問器類型是UISwitch控制項,那麼如何顯示自定義的訪問器呢?其實只要設置UITableViewCell的accessoryView即可,它支持任何UIView控制項。假設我們在通訊錄每組第一行放一個UISwitch,同時切換時可以輸出對應信息:
  1. // 
  2. //  KCMainViewController.m 
  3. //  UITableView 
  4. // 
  5. //  Created by Kenshin Cui on 14-3-1. 
  6. //  Copyright (c) 2014年 Kenshin Cui. All rights reserved. 
  7. // 
  8.  
  9. #import "KCMainViewController.h" 
  10. #import "KCContact.h" 
  11. #import "KCContactGroup.h" 
  12.  
  13. @interface KCMainViewController ()<uitableviewdatasource,uitableviewdelegate,uialertviewdelegate>{ 
  14.     UITableView *_tableView; 
  15.     NSMutableArray *_contacts;//聯繫人模型 
  16.     NSIndexPath *_selectedIndexPath;//當前選中的組和行 
  17.  
  18. @end 
  19.  
  20. @implementation KCMainViewController 
  21.  
  22. - (void)viewDidLoad { 
  23.     [super viewDidLoad]; 
  24.      
  25.     //初始化數據 
  26.     [self initData]; 
  27.      
  28.     //創建一個分組樣式的UITableView 
  29.     _tableView=[[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; 
  30.      
  31.     //設置數據源,註意必須實現對應的UITableViewDataSource協議 
  32.     _tableView.dataSource=self; 
  33.     //設置代理 
  34.     _tableView.delegate=self; 
  35.      
  36.     [self.view addSubview:_tableView]; 
  37.  
  38. #pragma mark 載入數據 
  39. -(void)initData{ 
  40.     _contacts=[[NSMutableArray alloc]init]; 
  41.      
  42.     KCContact *contact1=[KCContact initWithFirstName:@"Cui" andLastName:@"Kenshin" andPhoneNumber:@"18500131234"]; 
  43.     KCContact *contact2=[KCContact initWithFirstName:@"Cui" andLastName:@"Tom" andPhoneNumber:@"18500131237"]; 
  44.     KCContactGroup *group1=[KCContactGroup initWithName:@"C" andDetail:@"With names beginning with C" andContacts:[NSMutableArray arrayWithObjects:contact1,contact2, nil]]; 
  45.     [_contacts addObject:group1]; 
  46.      
  47.  
  48.      
  49.     KCContact *contact3=[KCContact initWithFirstName:@"Lee" andLastName:@"Terry" andPhoneNumber:@"18500131238"]; 
  50.     KCContact *contact4=[KCContact initWithFirstName:@"Lee" andLastName:@"Jack" andPhoneNumber:@"18500131239"]; 
  51.     KCContact *contact5=[KCContact initWithFirstName:@"Lee" andLastName:@"Rose" andPhoneNumber:@"18500131240"]; 
  52.     KCContactGroup *group2=[KCContactGroup initWithName:@"L" andDetail:@"With names beginning with L" andContacts:[NSMutableArray arrayWithObjects:contact3,contact4,contact5, nil]]; 
  53.     [_contacts addObject:group2]; 
  54.      
  55.      
  56.      
  57.     KCContact *contact6=[KCContact initWithFirstName:@"Sun" andLastName:@"Kaoru" andPhoneNumber:@"18500131235"]; 
  58.     KCContact *contact7=[KCContact initWithFirstName:@"Sun" andLastName:@"Rosa" andPhoneNumber:@"18500131236"]; 
  59.  
  60.     KCContactGroup *group3=[KCContactGroup initWithName:@"S" andDetail:@"With names beginning with S" andContacts:[NSMutableArray arrayWithObjects:contact6,contact7, nil]]; 
  61.     [_contacts addObject:group3]; 
  62.      
  63.      
  64.     KCContact *contact8=[KCContact initWithFirstName:@"Wang" andLastName:@"Stephone" andPhoneNumber:@"18500131241"]; 
  65.     KCContact *contact9=[KCContact initWithFirstName:@"Wang" andLastName:@"Lucy" andPhoneNumber:@"18500131242"]; 
  66.     KCContact *contact10=[KCContact initWithFirstName:@"Wang" andLastName:@"Lily" andPhoneNumber:@"18500131243"]; 
  67.     KCContact *contact11=[KCContact initWithFirstName:@"Wang" andLastName:@"Emily" andPhoneNumber:@"18500131244"]; 
  68.     KCContact *contact12=[KCContact initWithFirstName:@"Wang" andLastName:@"Andy" andPhoneNumber:@"18500131245"]; 
  69.     KCContactGroup *group4=[KCContactGroup initWithName:@"W" andDetail:@"Wi
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一般白色就是0,黑色就是1 單色點陣圖: 24位點陣圖 256色 安卓中預設使用32位的 將一個圖片放在SD卡上,使用BitmapFactory.decodeFile解析得Bitmap設置ImageView顯示 以上的圖片可以正常載入 異常現象 載入 的圖片過大,如2560*1520之類的,載入 時就會
  • 本文主要實現了微信的個人主頁的設置: 目錄文件如下: 實現代碼如下: RootTableViewController.h RootTableViewController.m AppDelegate.h AppDelegate.m 效果圖如下:
  • 主要在清單文件這樣配置: 2、那麼如何讓屏幕橫屏或者豎屏時對activity沒有影響呢?應當這樣配置:
  • 我們先看一下效果 代碼如下 首先是第一個頁面 rootTableViewController.h rootTableViewController.m 第二個頁面 cityTableViewController.h 第二個頁面 cityTableViewController.m 指定根目錄AppDel
  • 網路請求預設是get 網路請求有很多種:GET查 POST改 PUT增 DELETE刪 HEAD 在平時開發中主要用的 是 get 和 post. get 獲得數據 (獲取用戶信息) get 請求是沒有長度限制的,真正的長度限制是瀏覽器做的,限制長度一般2k get 請求是有緩存的,get 有冪等的
  • 字典 NSDictionary * dict = [[NSDictionary alloc] initWithObjectsAndKeys:@"One", @"1", @"Two", @"2", @"Three", @"3", @"One", @"4", nil]; //字典中的數據以鍵值對的方式進
  • 本篇分為兩部分: 第一步:首先創建 BMKMapView 視圖 第二步:在視圖完全顯示出來後設置,並實現代理方法 第三步:運行程式,此時大頭針效果可以正常顯示 第一步:延時載入對象 第二步:實現BMKPoiSearchDelegate代理方法 第三步:實現 BMKPoiSearchDelegate
  • 對於現在的iOS開發,用法簡單,最古老最經典最直接的NSURLConnection的作用不是很大,但是作為一名ios開發者,我們應該擁有一顆熱愛學習的心,下麵通過代碼的實現簡單介紹一下NSURLConnection。
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...