学习总结以及项目中的运用一:Delegate

来源:互联网 发布:java迷宫游戏代码 编辑:程序博客网 时间:2024/05/21 21:36

公司产品迭代的速度远超流星,小版本一星期,大版本半个月,这次迭代完可算轻松点所以决定写写这次的心得体会。首先这次是和同事协作开发共同完成一个模块,之前delegate也用过,只不过是简单的皮毛,这次感受到了一个好的设计模式对协作开发的重要性。不多说直接上代码


ReleasePostModel  

所有帖子页面Model的父类Model

@protocol ReleasePostModelDelegate <NSObject>

/*!

 @method - (void)addressValueChanged;

 @abstract “address”地址属性改变通知其代理

 */

- (void)addressValueChanged;

@end

@property(nonatomic,copy)NSString *address; //位置信息

@property(nonatomic,copy)NSString *m;//返回错误信息


有两个所有帖子通用的属性

这里对 address 使用KVO 进行监听,在address这个属性改变的时候调用  ReleasePostModelDelegate 这个代理

 <KVO 监听要及时在dealloc中remove,崩溃>


情景一:一个View 对应 一个ViewContorller  

比如这里所有控件是在View中的, ViewConrolle只负责相关动作,点击所在位置,会跳转到地图定位界面,当选择完为止,会给View.Model.address 赋值 ,这时会调用之前设置的KVO 调用View中的delegate方法 ,对所在位置这个UILabel进行重新刷新赋值。

这样的好处就是,控制器只需要单独对Model赋值即可完成数据的回调,控件的赋值

< 常规做法1:点击所在位置进入地图定位界面,选择完毕后block回调给VC然后通过View中的block,回调的参数 将新值Str赋给label.text和Model, (赋值了两次,这里block套block并不好)

<常规方法2:运用NSNotificationCenter进行属性传递,从通知的方法中调用属性.object 进行转换赋值 (赋值了两次)

<常规方法3:  建立一个Protocol文件,在View遵从这个协议,在VC中设一个id类型遵从protocol的成员变量ProtocolObject,将View赋给 ProtocolObject 从而在抵制回调的block中调用协议传值回View中进行属性赋值以及界面刷新

<常规方法4:  运用KVO进行键值监听,定位界面选择完 将回调的 地理信息 直接赋值给View.model.address   ,address改变时候 会调用delegate 重新对View中的LocationLabel赋值,这里只用对模型复制一次,保证了数据的统一性。

由上面四种方法 ,显而易见的,第四种更符合MVC思想,由数据Model去控制View的展示 。

!==图片选择==!

SelectImageView图片选择这地方同样也是说的View如何与VC传值问题

功能大概是这样的,点击照相机图片,进入相机拍照选取图片或者相册中选取图片,多选完会跳回帖子界面一行五个,超过五个会排到第二行。最多选择9张图片。点击选择的图片展示大图,可以移除图片,并且会随着图片数量进行界面更新。所以这里SelectImageViewDelegate中有三个代理方法:

@protocol SelectImageViewDelegate <NSObject>

- (void)selectImageAtIndex:(NSInteger)index;//点击图片选择展示大图

- (void)addImageFromAlbumOrCamera;//点击添加按钮添加图片

- (void)addOrRemoveImageView;//添加或删除图片

@end


首先SelectImageView是在单独的View中,但是要根据用户不同的操作进行不同的界面跳转以及界面显示(跳转逻辑现在View里肯定是不行的),所以SelectImageViewDelegate需要在VC中实现。

这里就需要用到上面提到的第三种方法了,因为第四种方法KVO链式设计模式并不适用。

首先先理理平时经常用的delegate模式:

A有个协议ADelegate,B去遵守A的协议。A在某种情况下调用了delegate中的方法,使B中执行了ADelegate中的相关方法。

但是这里会发现,我们是需要在SelectImageViewDelegate的代理方法中实现View中的Delegate,用上面常用的delegate逻辑是理不通的。

< 解决方案:建立一个Protocol类,里面写入两个方法

@protocol PostViewProtocol <NSObject>

@optional

/*!

 @method -(void)updateLocationButtonFrame;

 @abstract 刷新布局

 @return void

 */

-(void)updateLocationButtonFrame;


/*!

 @method - (void)releaseAllFirstResponser;

 @abstract 释放视图所有第一响应者

 @return void

 */

- (void)releaseAllFirstResponser;

@end


在VIew中分别将这两个方法实现并作对应的处理,刷新定位控件的位置,以及点击选择图片时要释放View第一响应者回收键盘。在VC中不需要遵循PostViewProtocol  ,只需要建立一个成员变量

id<PostViewProtocol> _postViewProtocol;

在相应位置,将View赋值给 _postViewProtocol (例如:_postViewProtocol = _PostView;)

然后在相应的SelectImageViewDelegate 方法中中调用PostViewProtocol中相应的方法即可(例如:[_releasePostViewProtocol releaseAllFirstResponser];)

这样结构层次很清晰,业务逻辑也不混乱,VC做VC该做的事情,View做View该做的事情






!==模型属性==!



这里其实还有一个问题,就是View上的值如何传递给VC进行网络数据请求的问题

因为发布Button实在VC的Nav上,所以点击发布buttn需要从View中拿到每个输入框中的数值,所以可以在PostViewProtocol中写一个赋值的方法


@required

/*!

 @method -(void)getTheUserInput;

 @abstract 将View数据赋值给对应的数据模型

 @return void

 */

-(void)getTheUserInput;


在VC的button点击实践中 调用 getTheUserInput  ,View中实现的getTheUserInput 方法里会吧相关的值赋值给对应的model属性。这样,这个PostViewProtocol 就是负责View的所有和VC中的逻辑交互。


那么问题又来了。View.model 中的属性如何进行网络请求发送给服务器呢。

一个一个在VC中赋值?完全不能看。

把Model中的属性放到一个字典里,然后在VC中调用View.model 的一个方法返回一个字典进行赋值?这样也不行,层次太混乱

这里呢还是用Protocol是最好的,建立一个专门用于管理Model属性的Delegate,postModelDelegate,这里有两个方法:

/*!

 @method - (BOOL)isDataAvailable;

 @abstract 判断数据是否可用

 @return YES:不可用,有数据为空; NO:数据可用

 */

- (BOOL)isDataAvailable;


/*!

 @method - (NSDictionary *)getRequestDetail;

 @abstract 获取提交到网络的详细封装数据

 @return 详细封装数据

 */

- (NSDictionary *)getRequestDetail;


在Model中,分别实现这两个方法,用前面提到的相同的方法,在对应的触发方法中调用delegate中对应的方法即可。


这里,这篇总结也差不多结束了,后面还有多个View对应一个VC的情景。以后再写,洗洗睡了



0 0
原创粉丝点击