前言:
最近需求作一个公共空间的需求,最后决定用适配器模式来做。
首先,需求是什么?
在我们app中,会有很多列表,tableviewcell的样式会比较统一(当然,我之前在公司那个app不算很大,基本每个列表都会有自己的主题,所以不太会统一,而现在的这个公司的作品主要是以名片为主,所以会设置很多名片的列表,不同情况会有不同规则,但大同小异),UI设计师给出了需要做成公告空间的所有cell,我们经过归类,分成了几种cell,几个cell要满足他给出的所有cell。
为什么会有这样的需求,因为当团队比较大的时候,有多个差不多的view是我们是自己做自己的,这样代码就好很冗余,并且还会有开发中写了一个视图控件但在项目好几个地方都用到了这个控件了,你在给这个视图控件赋值是怎么做呢?
-(void)laodData:(feedModel*)model; ?这样?
这么写没有错,而且很简单。但是有两点不好:
-
视图根数据模型有耦合,视图类引入了模型。
2.当你在项目里其他的地方用到了这个视图类,而且对应的模型不再是feedModel了,而是一个新的模型,这个时候你就需要再写一个初始化方法,如果有更多人使用,就会更多。
所以这个时候我们需要使用适配器模式。
那适配器模式是什么?
是将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
适用场景:
创建一个可以复用的类,使得该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作,为了让客户端尽可能的通用,我们使用适配器模式来隔离客户端与外部参数的联系,只让客户端与适配器通信.
撸代码了:
#import <Foundation/Foundation.h> @protocol TNFeedSmallLevelrProtocol <NSObject> @required - (NSString *)feedId; - (NSString *)headImageUrl; - (NSString *)title; - (NSString *)subtitle; - (NSString *)forumLevel; @optional - (UIEdgeInsets)contentBackgoundViewEdgeInset; @end
#import "TNSmallLevelCell.h" @implementation TNSmallLevelCell -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { [self.contentView addSubview:self.contentBackgoundAllView]; [self.contentBackgoundAllView addSubview:self.headImageView]; [self.contentBackgoundAllView addSubview:self.titleLable]; [self.contentBackgoundAllView addSubview:self.subtitleLable]; [self.contentBackgoundAllView addSubview:self.forumLevelView]; self.contentInset = UIEdgeInsetsZero; [self setNeedsUpdateConstraints]; } return self; } - (void)updateConstraints{ [super updateConstraints]; __weak typeof(self) weakSelf = self; [self.headImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(@12); make.left.mas_equalTo(weakSelf.contentBackgoundAllView.mas_left).offset(HI(15)); make.size.mas_equalTo(CGSizeMake(40, 40)); make.centerY.mas_equalTo(weakSelf.contentBackgoundAllView.mas_centerY); }]; [self.titleLable mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(weakSelf.headImageView.mas_right).offset(HI(10)); make.top.mas_equalTo(weakSelf.contentBackgoundAllView.mas_top).offset(WH(16)); make.height.mas_equalTo(16); make.right.lessThanOrEqualTo(weakSelf.contentBackgoundAllView.mas_right).offset(HI(-53)); }]; [self.subtitleLable mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(weakSelf.titleLable.mas_left); make.top.mas_equalTo(weakSelf.titleLable.mas_bottom).offset(WH(5)); make.right.lessThanOrEqualTo(weakSelf.contentBackgoundAllView.mas_right).offset(HI(-10)); make.height.mas_equalTo(@14); }]; [self.forumLevelView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(weakSelf.titleLable.mas_right).offset(HI(5)); make.size.mas_equalTo(CGSizeMake(38, 14)); make.centerY.mas_equalTo(weakSelf.titleLable.mas_centerY); }]; [self.contentBackgoundAllView mas_remakeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.contentInset); }]; } - (void)loadData:(id <TNFeedSmallLevelrProtocol>)data{ self.headImageView.imageUrlString = [data headImageUrl]; self.titleLable.text = [data title]; self.subtitleLable.text = [data subtitle]; [self.forumLevelView setTitle:[data forumLevel] forState:UIControlStateNormal]; if ([data respondsToSelector:@selector(contentBackgoundViewEdgeInset)]) { self.contentInset = [data contentBackgoundViewEdgeInset]; } } @end
#import "TNNormalAdeapter.h" #import "TNFeedModel.h" @implementation TNNormalAdeapter - (instancetype)initWithData:(id)data { if (self = [super init]) { self.data = data; } return self; } - (NSString *)headImageUrl { TNFeedModel *model = self.data; return model.headImageUrl; } - (NSString *)title { TNFeedModel *model = self.data; return model.title; } - (NSString *)subtitle { TNFeedModel *model = self.data; return model.subtitle; } -(NSString *)forumLevel { TNFeedModel *model = self.data; return model.forumLevel; } @end
#import <Foundation/Foundation.h> #import "TNFeedGroupSelfIdentityProtocol.h" @interface TNFeedModel : NSObject @property (nonatomic, copy)NSString *headImageUrl; @property (nonatomic, copy)NSString *title; @property (nonatomic, copy)NSString *subtitle; @property (nonatomic, copy)NSString *forumLevel; @property (nonatomic, assign)BOOL subtitleIsShow; @end
注意几个问题:
1.除了每一个view都需要显示的控件默认显示外,其他控件默认都不显示。(因为,当其他小伙伴用的view是需要什么,他就设置什么属性就可以,他不应该去考虑和他没有关系的任何属性)
2.协议里分 必须实现的 和 非必需实现的 两种属性
需要注意的是:非必需实现的属性用数据的时候需要判断,他是否在适配器里实现了,不然会crash
结语:
互相学习,如果有总结不对的地方,请大家指出。
参考:
https://www.cnblogs.com/YouXianMing/p/4676508.html
http://www.cocoachina.com/ios/20161013/17740.html