IOS 学习笔记 20150327 我理解的OC代理模式

IOS 学习笔记 20150327 我理解的OC代理模式

IOS 学习笔记 20150327 我理解的OC代理模式

案例1

KCButton.h

//
//  KCButton.h
//  Protocol&Block&Category
//
//  Created by Kenshin Cui on 14-2-2.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <Foundation/Foundation.h>
@class KCButton;

//一个协议可以扩展另一个协议,例如KCButtonDelegate扩展了NSObject协议
@protocol KCButtonDelegate <NSObject>

@required //@required修饰的方法必须实现
-(void)onClick:(KCButton *)button;

@optional //@optional修饰的方法是可选实现的
-(void)onMouseover:(KCButton *)button;
-(void)onMouseout:(KCButton *)button;

@end

@interface KCButton : NSObject

#pragma mark - 属性
#pragma mark 代理属性,同时约定作为代理的对象必须实现KCButtonDelegate协议
@property (nonatomic,retain) id<KCButtonDelegate> delegate;

#pragma mark - 公共方法
#pragma mark 点击方法
-(void)click;

@end
KCButton.m

//
//  KCButton.m
//  Protocol&Block&Category
//
//  Created by Kenshin Cui on 14-2-2.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import "KCButton.h"

@implementation KCButton

-(void)click{
    NSLog(@"Invoke KCButton's click method.");
    //判断_delegate实例是否实现了onClick:方法(注意方法名是"onClick:",后面有个:)
    //避免未实现ButtonDelegate的类也作为KCButton的监听
    if([_delegate respondsToSelector:@selector(onClick:)]){
        [_delegate onClick:self];
    }
}

@end
MyListener.h

//
//  MyListener.h
//  Protocol&Block&Category
//
//  Created by Kenshin Cui on 14-2-2.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <Foundation/Foundation.h>
@class KCButton;
@protocol KCButtonDelegate;

@interface MyListener : NSObject<KCButtonDelegate>
-(void)onClick:(KCButton *)button;
@end
MyListener.m

//
//  MyListener.m
//  Protocol&Block&Category
//
//  Created by Kenshin Cui on 14-2-2.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import "MyListener.h"
#import "KCButton.h"

@implementation MyListener
-(void)onClick:(KCButton *)button{
    NSLog(@"Invoke MyListener's onClick method.The button is:%@.",button);
}
@end
main.m

//
//  main.m
//  Protocol&Block&Category
//
//  Created by Kenshin Cui on 14-2-2.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "KCButton.h"
#import "MyListener.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        KCButton *button=[[KCButton alloc]init];
        MyListener *listener=[[MyListener alloc]init];
        button.delegate=listener;
        [button click];
        /* 结果:
         Invoke KCButton's click method.
         Invoke MyListener's onClick method.The button is:<KCButton: 0x1001034c0>.
         */
    }
    return 0;
}
我们通过例子模拟了一个按钮的点击过程,有点类似于Java中事件的实现机制。通过这个例子我们需要注意以下几点内容:

id可以表示任何一个ObjC对象类型,类型后面的”<协议名>“用于约束作为这个属性的对象必须实现该协议(注意:使用id定义的对象类型不需要加“*”);
MyListener作为事件触发者,它实现了KCButtonDelegate代理(在ObjC中没有命名空间和包的概念,通常通过前缀进行类的划分,“KC”是我们自定义的前缀)
在.h文件中如果使用了另一个文件的类或协议我们[email protected]@protocol进行声明,而不必导入这个文件,这样可以提高编译效率([email protected]@protocol,例如上面KCButton.h中上面声明的KCButtonDelegate协议中用到了KCButton类,而此文件下方的KCButton类声明中又使用了KCButtonDelegate,从而形成在一个文件中互相引用关系,[email protected]@protocol声明,否则编译阶段会报错),但是在.m文件中则必须导入对应的类声明文件或协议文件(如果不导入虽然语法检查可以通过但是编译链接会报错);
使用respondsToSelector方法可以判断一个对象是否实现了某个方法(需要注意方法名不是”onClick”而是“onClick:”,冒号也是方法名的一部分);
属性中的(nonatomic,retain)不是这篇文章的重点,在接下来的文章中我们会具体介绍。

 

案例2

//
//  WPContactsViewController.h
//  OC-UI-表单-单元格
//
//  Created by wangtouwang on 15/3/26.
//  Copyright (c) 2015年 wangtouwang. All rights reserved.
//

#import <UIKit/UIKit.h>


@interface WPContactsViewController : UIViewController
{
    UITableView *_tableView;//表单UI控件
    NSMutableArray *_mutableArrayContacts;//联系人集合模型
    NSIndexPath *_selectedIndexPath;//当前选中的组和行
}

@end
//
//  WPContactsViewController.m
//  OC-UI-表单-单元格
//
//  Created by wangtouwang on 15/3/26.
//  Copyright (c) 2015年 wangtouwang. All rights reserved.
//

#import "WPContactsViewController.h"
#import "WPContacts.h"
#import "WPContactsGroup.h"

@interface WPContactsViewController ()<UITableViewDataSource,UITableViewDelegate,UIAlertViewDelegate>

@end


@implementation WPContactsViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //初始化数据
    [self initObjectData];
    
    //创建一个分组样式的UITableView
    _tableView=[[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
    
    //设置数据源,注意必须实现对应的UITableViewDataSource协议
    _tableView.dataSource=self;
    
    //设置代理
    _tableView.delegate=self;
    
    [self.view addSubview:_tableView];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark 加载数据
-(void)initObjectData{
     _mutableArrayContacts=[[NSMutableArray alloc]init];
    
    WPContacts *contact1=[WPContacts initStaticWithFirstName:@"Cui" andLastName:@"Kenshin" andPhoneNumber:@"18500131234"];
    WPContacts *contact2=[WPContacts initStaticWithFirstName:@"Cui" andLastName:@"Tom" andPhoneNumber:@"18500131237"];
    WPContactsGroup *group1=[WPContactsGroup initStaticWithName:@"C" andDescript:@"With names beginning with C" andConcats:[NSMutableArray arrayWithObjects:contact1,contact2, nil]];
    [_mutableArrayContacts addObject:group1];
 
    
    WPContacts *contact3=[WPContacts initStaticWithFirstName:@"Dui" andLastName:@"JACK" andPhoneNumber:@"13712121"];
    WPContacts *contact4=[WPContacts initStaticWithFirstName:@"Dui" andLastName:@"LUCY" andPhoneNumber:@"13712122"];
    WPContactsGroup *group2=[WPContactsGroup initStaticWithName:@"D" andDescript:@"With names beginning with D" andConcats:[NSMutableArray arrayWithObjects:contact3,contact4, nil]];
    [_mutableArrayContacts addObject:group2];
    
}

#pragma mark 返回分组数
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    NSLog(@"计算分组数");
    return _mutableArrayContacts.count;
}

#pragma mark 返回每组行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    NSLog(@"计算每组(组%lu)行数",(unsigned long)section);
//    WPContactsGroup *group1 = _mutableArrayContacts[section];
    return  ((WPContactsGroup *)_mutableArrayContacts[section])._concats.count;
}

#pragma mark返回每行的单元格
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
     NSLog(@"生成单元格(组:%lu,行%lu)",(unsigned long)indexPath.section,(unsigned long)indexPath.row);
   WPContactsGroup *group= _mutableArrayContacts[indexPath.section];
    WPContacts *contacts = group._concats[indexPath.row];
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil];
    cell.textLabel.text=[contacts getName];
    cell.detailTextLabel.text = [contacts _phoneNumber];
    return cell;
}

#pragma mark 返回每组头标题名称
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
     NSLog(@"生成组(组%lu)名称",(unsigned long)section);
    WPContactsGroup *group =  _mutableArrayContacts[section];
    return group._name;
}

#pragma mark 返回每组尾部说明
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{
    NSLog(@"生成尾部(组%lu)详情",(unsigned long)section);
    return ((WPContactsGroup *)_mutableArrayContacts[section])._descript;
}


#pragma mark 生成索引
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{
    NSLog(@"生成组索引");
    NSMutableArray *indexs = [[NSMutableArray alloc] init];
    for (WPContactsGroup *group in _mutableArrayContacts) {
        [indexs addObject:group._name];
    }
    return indexs;
}

#pragma mark 设置分组标题高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    NSLog(@"设置分组标题高度");
    return 25;
}

#pragma mark 设置分组尾部内容高度
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
    NSLog(@"设置分组尾部内容高度");
    return 20;
}

#pragma mark 设置每行高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
       NSLog(@"设置每行高度");
    return 30;
}

#pragma mark 复写设置点击行触发事件(复写的方法是在TableViewDelegate协议中已有,回调)
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    NSLog(@"触发我吧");
     _selectedIndexPath=indexPath;
    //获取单元格包装的对象WPContacts
   WPContacts *contacts = ((WPContactsGroup *)_mutableArrayContacts[indexPath.section])._concats[indexPath.row];
    //初始化弹出框
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"System Info" message:[contacts getName] delegate:self cancelButtonTitle:@"Cancle" otherButtonTitles:@"OK", nil];
    //设置窗口样式
    alertView.alertViewStyle=UIAlertViewStylePlainTextInput;
    //获取文本框
    UITextField *textFild =  [alertView textFieldAtIndex:0];
    //设置文本框内容
    textFild.text = contacts._phoneNumber;
    //显示窗口
    [alertView show];
}

#pragma mark 设置弹出框后续按钮事件 复写UIAlerViewDelegate协议 的点击按钮 clickedButtonAtIndex方法
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    NSLog(@"设置弹出框后续按钮事件 clickedButtonAtIndex");
    if (buttonIndex==1) {
        //获取文本框内容
        NSString *phoneNumber = [alertView textFieldAtIndex:0].text;    
        //获取选中的UITableViewCell 包装的对象
       WPContacts *contacts =  ((WPContactsGroup *)_mutableArrayContacts[_selectedIndexPath.section])._concats[_selectedIndexPath.row];
        contacts._phoneNumber = phoneNumber;
        
         NSArray *indexPaths=@[_selectedIndexPath];//需要局部刷新的单元格的组、行
            //此处优化 将全局跟新 该变到 选择行 局部更新
        [_tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationLeft];
        
        //[_tableView reloadData];
    }
}

@end

 

 

 

 
更多相关文章
  • IOS学习笔记06C语言函数 --  qq交流群:创梦技术交流群:251572072                        创梦网络赚钱群:248318056                        创梦娱乐休闲群:224801824  教程下载,在线交流:创梦IT社区:www.cre ...
  • IOS学习笔记07C语言函数-printf函数 0 7.C语言5-printf函数 - qq交流群:创梦技术交流群:251572072                         创梦网络赚钱群:248318056                         创梦娱乐休闲群:22480182 ...
  • 置顶 iOS学习笔记47——图片异步加载之EGOImageLoading
    上次在<iOS学习笔记46——图片异步加载之SDWebImage>中介绍过一个开源的图片异步加载库,今天来介绍另外一个功能类似的EGOImageLoading,看名字知道,之前的一篇学习笔记<IOS学习笔记34—EGOTableViewPullRefresh实现下拉刷新>中介 ...
  • iOS 学习笔记——0007(界面浅谈)
    1.iOS界面常识 ①statusbar的高度为20px(像素),[[UIApplication sharedApplication]statusBarFrame]//可以打印状态栏的rect look look的 ② 手机型号 尺寸 分辨率 对应图片分辨率 4/4s 3.5 320*480 @2x ...
  • tyle="margin:20px 0px 0px; line-height:26px; font-family:Arial"> #include         区分 #include <x.h>与#include "x.h"的作用     ...
  •   先发一个练手的小demo,自己写的简略通讯录,已上传至github https://github.com/liaoshaolim/addressBook   1.NSKeyedArchiver:(归档) 这里用一个添加联系人的例子来说明: 注意:归档形式保存数据,需要该对象遵守NSCoding协 ...
  •      近期由于IOS7的发布,所以应用的适配潮可谓是都搞的锣鼓喧天,甚是热闹,因此呢,因适配IOS7而产生的问题也是铺天盖地的卷来,所以了,我也从简单的状态栏适配开始,先研究了下关于状态栏的适配,特总结如下,供广大网友一起讨论交流. PS:首先说明下,ios7中,由于status bar不再占用 ...
  • 首页 > 程序开发 > 移动开发 > IOS > 正文 iOS 获取手机的型号,系统版本,软件名称,软件版本 2012-10-20 0 个评论 作者:vipa1 收藏 我要投稿 网上搜索出来的,记录下来以后使用方便: [java] //手机序列号 NSString* iden ...
一周排行