AJ分享,必須精品
先看效果圖



### 源代碼
# NYViewController的代碼
~~~
#import "NYViewController.h"
#import "NYHero.h"
@interface NYViewController () <UITableViewDataSource,UITableViewDelegate>
@property (strong,nonatomic) UITableView *tableView;
@property (strong,nonatomic) NSArray *heros;
@end
@implementation NYViewController
-(NSArray *)heros
{
if (_heros == nil)_heros = [NYHero heros];
return _heros;
}
/**懶加載tableView
*/
-(UITableView *)tableView
{
if (_tableView == nil) {
//表格控件在創建時必須指定樣式
// UITableViewStylePlain 平板格式
// UITableViewStyleGrouped分組格式
_tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
//添加數據源->加入協議
_tableView.dataSource = self;
/*設置行高方法有兩種,代理方法的優先級比setRowHeight的優先級高。
應用場景,很多應用程序,每一行高度是不一樣的,例如:新浪微博
*/
// _tableView.rowHeight = 80;//第一種
_tableView.delegate = self;//第二種,要設置代理,-》協議 -》實現代理方法
[self.view addSubview:_tableView];
}
return _tableView;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self tableView];
}
#pragma mark - 數據源方法
/**每個分組中的數據總數*/
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.heros.count;
}
/**告訴表格,每個單元格的明細*/
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/*
UITableViewCellStyleDefault 默認類型 標題+可選圖像
UITableViewCellStyleValue1 標題+明細+圖像
UITableViewCellStyleValue2 不顯示圖像,標題+明細
UITableViewCellStyleSubtitle 標題+明細+圖像
*/
NSLog(@"表格行明細 %d",indexPath.row);
//static 靜態變量,能夠保證系統為變量在內存中只分配一次內存空間
//靜態變量,一旦創建,就不會被釋放,只有在應用程序在銷毀是,才會釋放。
static NSString *ID = @"cell";
//1,去緩存池查找可重復用得單元格
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
//2,如果沒找到
if (cell == nil) {
// NSLog(@"實例化單元格");
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
//設置單元格內容
// 取出英雄對象
NYHero *hero = self.heros[indexPath.row];
//設置標題 :英雄名字
cell.textLabel.text = hero.name;
//設置詳細內容: 英雄描述
cell.detailTextLabel.text = hero.intro;
//設置英雄圖標
cell.imageView.image = [UIImage imageNamed:hero.icon];
// 設置右邊的箭頭
// 1> UITableViewCellAccessoryDisclosureIndicator 箭頭,可以"提示"用戶,當前行是可以點擊的,通常選中行,會跳到新的頁面
// 2> UITableViewCellAccessoryCheckmark 對號,通常提示用戶該行數據設置完畢,使用的比較少
// 3> UITableViewCellAccessoryDetailButton 按鈕,通常點擊按鈕可以做獨立的操作,例如alertView
// 點擊按鈕并不會選中行
// 4> UITableViewCellAccessoryDetailDisclosureButton 按鈕+箭頭,各自操作
// cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
// 指定右側的自定義視圖
/**
通常accessoryType提供的類型不能滿足時,才會使用自定義控件
但是需要自行添加監聽方法,通常用在自定義cell,不要寫在視圖控制器中!!!
自定義控件的事件觸發,同樣不會影響表格行的選中!
*/
// UISwitch *switcher = [[UISwitch alloc] init];
// //添加監聽方法
// [switcher addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
//
// cell.accessoryView = switcher;
return cell;
}
-(void)switchChanged:(UISwitch *) sender
{
NSLog(@"%s %@", __func__, sender);
}
#pragma mark - 實現代理方法 (行高設置)
/**設置行高,比setRowHeight優先級高*/
-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70;
}
// 取消選中某一行,極少用,極容易出錯!
// didDeselectRowAtIndexPath
// didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"%s %@", __func__, indexPath);
}
/**選中了某一行*/
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"%s %@",__func__, indexPath);
}
/**
accessoryType為按鈕時,UITableViewCellAccessoryDetailButton點擊右側按鈕的監聽方法
此方法不會觸發行選中,跟行選中各自獨立
只是為accessoryType服務,對自定義控件不響應 */
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"%s %@", __func__, indexPath);
}
@end
~~~
### 模型的代碼的代碼
~~~
#import <Foundation/Foundation.h>
@interface NYHero : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *icon;
@property (nonatomic, copy) NSString *intro;
-(instancetype) initWithDict:(NSDictionary *)dict;
+(instancetype) heroWithDict:(NSDictionary *)dict;
+(NSArray *) heros;
@end
~~~
m實現文件
~~~
//
// NYHero.m
// 06 - lol英雄聯盟
//
// Created by apple on 15-3-28.
// Copyright (c) 2015年 znycat. All rights reserved.
//
#import "NYHero.h"
@implementation NYHero
-(instancetype)initWithDict:(NSDictionary *)dict
{
self = [super init];
if (self) {
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
+(instancetype)heroWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
+(NSArray *)heros
{
NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"heros.plist" ofType:nil]];
NSMutableArray *arrayM = [NSMutableArray array];
for (NSDictionary *dict in array) {
// 這才是應該寫的
[arrayM addObject:[self heroWithDict:dict]];
}
return arrayM;
}
@end
~~~
### ——關于字典模型的類方法
AJ今天犯二了,字典初始化方法中又一個竟然這么寫了,不多說了,大家看看引以為見吧
~~~
@implementation NYHero
-(instancetype)initWithDict:(NSDictionary *)dict
{
self = [super init];
if (self) {
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
+(instancetype)heroWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
+(NSArray *)heros
{
NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"heros.plist" ofType:nil]];
NSMutableArray *arrayM = [NSMutableArray array];
for (NSDictionary *dict in array) {
//這里我原來是這么寫的(注釋的是錯誤的)
//arrayM =[self heroWithDict:dict];
// 這才是應該寫的
[arrayM addObject:[self heroWithDict:dict]];
}
~~~
這二犯的,關鍵用debug你看的話,他會有內容,但是因為名稱差不太多,應該是heros返回值是一堆對象組成的數組,結果你NSLog就發現,他丫的就返回一個地址值,很奇怪,開始我還以為是xcode大姨媽來了呢。。。事實證明,代碼里面無秘密啊。
——————話說這好像是AJ寫的代碼中注釋最少的耶。。。
### 代理模式階段性小結
監聽控件的某些事件
使用代理模式,是為了在程序直接“解耦”。
表格可以顯示非常豐富的數據,為了達到這一結果,設置表格的“數據源”。
@required 必須實現的方法。
@optional 可選的實現方法->不強求實現->如果實現了能得到特殊的效果,如果不實現,也不影響程序的正常運行——能夠增加控件的靈活度。
代理階段性小結:(怎么用)
1,遵守協議,預先定義好方法,不實現,具體的實現工作由代理負責。
<控件的名字+DataSource> 定義的與數據有關的方法。
<控件的名字+Delegate> 定義的與事件有關的方法(通常用來監聽控件事件)。
2,代理方法:
1> 方法名以控件名稱開頭(沒有類前綴) -> 方便程序員書寫的時候,快速找到需要的協議方法。
2> 第一個參數是自己 -> 意味著在協議方法中,可以直接訪問對象的屬性,或調用方法。
3> 代理方法的返回值 -> 控制器向控件(委托)發送數據 。
### cell——UITableViewCell的注意點
緩存池的運用(老板本,后面會有新的東西更新,但是需要了解,看別人程序時候別不認識了——還有方便理解)
~~~
//1,去緩存池查找可重復用得單元格
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
//2,如果沒找到
if (cell == nil) {
// NSLog(@"實例化單元格");
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
//3設置單元格內容
//4return cell
~~~
初始化的時候需要指定cell的樣式
UITableViewCellStyleDefault 默認類型 標題+可選圖像
UITableViewCellStyleValue1 標題+明細+圖像
UITableViewCellStyleValue2 不顯示圖像,標題+明細
UITableViewCellStyleSubtitle 標題+明細+圖像
用法:
~~~
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
~~~
### 指定cell右側的視圖
設置右邊的箭頭
1> UITableViewCellAccessoryDisclosureIndicator 箭頭,可以”提示”用戶,當前行是可以點擊的,通常選中行,會跳到新的頁面
2> UITableViewCellAccessoryCheckmark 對號,通常提示用戶該行數據設置完畢,使用的比較少
3> UITableViewCellAccessoryDetailButton 按鈕,通常點擊按鈕可以做獨立的操作,例如alertView
點擊按鈕并不會選中行
4> UITableViewCellAccessoryDetailDisclosureButton 按鈕+箭頭,各自操作
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
指定右側的自定義視圖(例:選擇按鈕)
通常accessoryType提供的類型不能滿足時,才會使用自定義控件
但是需要自行添加監聽方法,通常用在自定義cell,不要寫在視圖控制器中!!!
自定義控件的事件觸發,同樣不會影響表格行的選中!
~~~
UISwitch *switcher = [[UISwitch alloc] init];
//添加監聽方法
[switcher addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = switcher;
~~~
?
?