iOS-通過繼承UIScrollView來自定義UITableView實現對代理的詳解

文明轉載評論是對自己尊重也是對學者的鼓勵

             iOS-通過繼承UIScrollView來自定義UITableView實現對代理的詳解


一.自定義UITableView     (CustomerTableView繼承於UIScrollView)

實現一個類繼承至UIScrollView,通過代理的語法模式實現UITableView的獲得UITableviewCell和UITableviewCell的佈局的原理,從而加深對UITableview的原理及對代理模式的理解。

CustomerTableView.h頭文件
#import <UIKit/UIKit.h>
@class CustomerTableView;

@protocol CustomerTableViewDelegate <NSObject>
//返回cell的個數
-(NSInteger)numberCellForCustomerTableView:(CustomerTableView *)customerView;
//返回cell的高度
-(CGFloat)cellHeightForCustomerTableView:(CustomerTableView *)customerView ;
//相當於cell
-(UIView *)customerTableView:(CustomerTableView *)customerView cellForIndex:(NSInteger)index;
//返回標題
-(NSString *)customerTableView:(CustomerTableView *)customerView titleForIndex:(NSInteger)index;

@end

@interface CustomerTableView : UIScrollView
//代理
@property (nonatomic,assign)id<CustomerTableViewDelegate> customerDelegate;
//設置代理和frame
-(id)initWithDelegate:(id<CustomerTableViewDelegate>)aDelegate andFrame:(CGRect)aFrame;


@end


CustomerTableView.m文件

#import "CustomerTableView.h"

@implementation CustomerTableView

-(id)initWithDelegate:(id<CustomerTableViewDelegate>)aDelegate andFrame:(CGRect)aFrame{
    if (self = [super initWithFrame:aFrame]) {
        
        self.frame = aFrame;
        //通過代理得到多少個cell
        int numberCell = (int)[aDelegate numberCellForCustomerTableView:self];
        //通過代理得到cell的高度,用來設置cell的佈局
        CGFloat cellHeight = [aDelegate cellHeightForCustomerTableView:self];
        
        CGFloat width = CGRectGetWidth(aFrame);
        CGFloat height = CGRectGetHeight(aFrame);
        
        //根據cell的個數來設置contentSize
        self.contentSize = CGSizeMake(width, numberCell*cellHeight);
        
        
        //循環的通過代理來拿到cell  title  並根據索引i來設置它們的位置,其他的屬性又屬性設置
        for (int i=0; i<numberCell; i++) {
            
            UIView *cell = [aDelegate customerTableView:self cellForIndex:i];
            cell.frame = CGRectMake(0, cellHeight*i, width, cellHeight);
            [self addSubview:cell];
            
            NSString *title = [aDelegate customerTableView:self titleForIndex:i];
            
            UILabel *lable = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, width, cellHeight)];
            lable.backgroundColor = [UIColor brownColor];
            lable.text = title;
            [cell addSubview:lable];
            
        }
        
        
    }
    return self;
}

@end

使用:
#import "ViewController.h"
#import "CustomerTableView.h"

@interface ViewController ()<CustomerTableViewDelegate>
@end
@implementation ViewController{
}
- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    CustomerTableView *customer = [[CustomerTableView alloc]initWithDelegate:self andFrame:CGRectMake(0, 0, 320, 400)];
    customer.showsHorizontalScrollIndicator = NO;
    customer.backgroundColor = [UIColor purpleColor];
    [self.view addSubview:customer];
    
    
}

//返回cell的高度
-(CGFloat)cellHeightForCustomerTableView:(CustomerTableView *)customerView{
    return 100;
}
//返回對應索引的的名字
-(NSString *)customerTableView:(CustomerTableView *)customerView titleForIndex:(NSInteger)index{
    return [NSString stringWithFormat:@"item %ld",index];
}
//相當於UITableView的返回cell
-(UIView *)customerTableView:(CustomerTableView *)customerView cellForIndex:(NSInteger)index{
    UIView *v = [[UIView alloc]init];
    v.backgroundColor = [UIColor redColor];
    return v;
}
//返回cell的個數
-(NSInteger)numberCellForCustomerTableView:(CustomerTableView *)customerView{
    return 10;
}

@end



運行效果:




二.UITableView的使用

    UITableView *table = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 400)];
    table.delegate = self;
    table.dataSource = self;
    [self.view addSubview:table];

代理使用:

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}


//相當於CustomerTableview返回多少個cell
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return 10;
}

//相當於CustomerTableView 的UIView的高度
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 100;
}

//相當於CustomerTableview   的UIView
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    cell.textLabel.text = [NSString stringWithFormat:@"item%ld",indexPath.row];
    return cell;
}


運行效果:




三.兩者對比了解代理模式


委託持有代理的引用,代理實現協議,委託通過代理得到代理服務。就比如你要找房子你要找一個陽光好的,價格少於1000元。房產中介能爲你找房,它能提供很多的房源,有陽光好的少於1000的家電齊全等等,現在你們並沒有什麼關係,如果你想找房不可能呆在家裏,於是你找了一家房產中介,這時你就成了委託方法,這時們就會簽署一式兩份的找房協議,上面有你的簽名和中介的簽名,你們各持有一份,這時你們就建立了委託代理的關係,這時你關係的不是中介提供的其他服務,你只關心簽署協議中的條件。然後中介就會拿出符合條件的房源給你。這就是生活中的代理模式的例子。

上面只是一個簡單的代理的生活抽象。把它映射到代碼中又會是什麼樣了:

@protocol   someDelegate<NSObject>   //你們要簽署的協議,這個協議是由你來提出
-(house*)getHouse;                                 //要找的房子
@end

@interface some
@property (assign,nonautomic)id<someDelegate> delegate;     //你去找了哪家的代理中介
@end



@interface agent()<someDelegate>    //實現找房的協議
@end
@implement agent
-(house *)getHouse{ //找到符合條件的房子
return house;
@end


委託和代理建立聯繫,上面只是代碼的設計。

運行時纔是真實場景的存在:

some *you =[[some alloc]init];  //你出現了
agent  *agent =[ [agen alloc]init] //房產中介出現了

上面兩步委託和代理沒有建立委託代理的關係
you.delegate = agent;        //委託代理建立了關係,相當於簽署了找房協議


[you.delegate  getHouse]  //這樣你就能通過代理給你找到房子了。


運行時內存狀態抽象圖:







總結:代理模式隨處可見,一般在MVC設計模式中,V(視圖)層常常通過代理C(控制)層得到要顯示的數據,並把用戶對V(視圖)層的操作傳給C(控制)層,讓C做相應的處理。如上中的UITableView (視圖層)  UIViewController(控制層),UITalbleView通過UIViewController的到數據,也可以把用戶的操作傳到UIViewController,所以任何的設計模式只要把它映射成C語言的數據和函數,就會更容易理解各種模式的設計原理。






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章