扯两句 MVC 的设计模式
DarPlain
8年前
<p><img src="https://simg.open-open.com/show/f9fbaf0ee4726e6d991ede4ace4fe5cf.png"></p> <p>一个app开发的主要流程可以简单概括为:</p> <p>搭建UI界面—> 请求服务器数据 —> 把数据展示在UI界面上 –> 处理UI界面的业务逻辑 —> 测试及优化</p> <p>在编程世界里面大家都知道一句话: 高内聚,低耦合</p> <ul> <li> <p>高内聚,就是指尽量让一个类或者一个方法它专门去处理一个事情,对外只提供一个接口,内部具体如何实现不需要告诉外界.</p> </li> <li> <p>低耦合,就是减少类与类之间相互的依赖性,降低代码的入侵性,当改变一个类中的一个东西时候,不需要另一个类中也大批量改.</p> </li> </ul> <p>我们在请求网络数据的时候,通常服务器给我们返回都是json或者xml数据,我们利用第三方框架将它解析之后会得到一个 <strong>字典数组</strong> .</p> <p>这时候如果我们面向字典来开发:</p> <p>1.这样不太符合我们 <strong>面向对象</strong> 开发的伟大思想觉悟</p> <p>2.由于xcode的原因,在敲字典的key时候系统是不会给我们提示(也就是自动联想功能)的,这样容易造成我们有时候不小心敲错了一个key导致加载不出数据,但是系统又不会报错,代码一多很可能就要花很多时间去找八哥(bug),专业点来讲就是 <strong>容错率低</strong> .</p> <p>所以为了顺应社会主义发展的步伐,我们需要将 <strong>字典数组</strong> 转换为 <strong>模型数组</strong> ,也就是将字典转为模型, 这就要扯到MVC这个设计模式了.</p> <p>MVC是三个单词的首字母缩写, 他们分别是 , 他们分别是, 分别是Model, View, Controller, 也就是模型, 视图, 控制器.</p> <ul> <li> <p>Model : 继承NSObject, 负责保存数据.</p> </li> <li> <p>View : 视图控件, 通常用xib来描述它里面的子控件,负责将数据展示在UI界面上</p> </li> <li> <p>Controller : 控制器,负责请求及处理网络数据, 处理用户交互</p> </li> </ul> <p>他们三兄弟的关系如下:</p> <p><img src="https://simg.open-open.com/show/947cfd64517ba2376daf5988caded341.png"></p> <p>这样子,他们三个各司其职, 符合我们高内聚,低耦合的思想.</p> <p>下面用简单的table view实例来阐述一下MVC的使用,如下图的效果</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/b9f8d1660bf86a60c3735fa1f5168c4d.png"></p> <p>谁能教教我用markdown放入图片怎么设置图片大小?</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/1e5111a1379599779de8d4aeb8dfae32.png"></p> <p>1.在Model(也叫Item)里面定义属性,用来保存网络数据</p> <pre> <code class="language-objectivec">#import @interface tagItem : NSObject @property(nonatomic,strong)NSString *image_list; @property(nonatomic,strong)NSString *sub_number; @property(nonatomic,strong)NSString *theme_name; @end </code></pre> <p>2.在Controller里面,请求数据,用第三方框架把数据转化成模型存进Model这个类中, 然后给cell的item属性赋值,这样子就可以把item(数据)传进View里面——简单的说,就是在Controller里面把数据传进View里面</p> <pre> <code class="language-objectivec">//发送网络请求 -(void)loadData { AFHTTPSessionManager *mgr = [AFHTTPSessionManagerljw_manager]; NSMutableDictionary *parameters = [NSMutableDictionarydictionary]; parameters[@"a"] = @"tag_recommend"; parameters[@"action"] = @"sub"; parameters[@"c"] = @"topic"; self.mgr = mgr; [mgrGET:@"http://api.budejie.com/api/api_open.php" parameters:parametersprogress:nilsuccess:^(NSURLSessionDataTask * _Nonnulltask, NSDictionary * _NullableresponseObject) { //字典数组转模型数组 _tags = [tagItemmj_objectArrayWithKeyValuesArray:responseObject]; [self.tableViewreloadData]; [SVProgressHUDdismiss]; } failure:^(NSURLSessionDataTask * _Nullabletask, NSError * _Nonnullerror) { NSLog(@"%@",error); [SVProgressHUDdismiss]; }]; } </code></pre> <pre> <code class="language-objectivec">#pragma mark - Table view data source //设置cell的高度 -(CGFloat)tableView:(UITableView *)tableViewheightForRowAtIndexPath:(NSIndexPath *)indexPath { return 60 + 10; } - (NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section { return _tags.count; } -(UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath { LJWAllTableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:ID]; tagItem *item = _tags[indexPath.row]; //把数据传给cell cell.item = item; return cell; } </code></pre> <p>3.在View里面描述好xib,</p> <p>然后定义item这个属性,并把各子控件拖好线,</p> <p>重写item这个属性的getter方法(因为在控制器中给item属性赋值时候就会调用这个方法), 在这个setter方法中用这个item的各个属性来给View的子控件赋值, 达到把数据展示在UI界面上的目的—简单来说就是在View里面拿到Model数据,把数据展示在View上</p> <pre> <code class="language-objectivec">#import "LJWAllTableViewCell.h" #import "tagItem.h" @interface LJWAllTableViewCell() @property (weak, nonatomic) IBOutletUILabel *nameLabel; @property (weak, nonatomic) IBOutletUILabel *numberLabel; @property (weak, nonatomic) IBOutletUIImageView *imageV; @end -(void)setItem:(tagItem *)item { _item = item; //名字********************* _nameLabel.text = item.theme_name; //订阅数****************** NSString *numStr = [NSStringstringWithFormat:@"%@人订阅",_item.theme_name]; CGFloatnum = [_item.sub_numberfloatValue]; if (num > 10000) { num = num / 10000; numStr = [NSStringstringWithFormat:@"%.1f人订阅",num]; } _numberLabel.text = numStr; //图片 ******************** [_imageVsd_setImageWithURL:[NSURLURLWithString:_item.image_list] placeholderImage:[UIImageimageNamed:@"defaultUserIcon"] completed:^(UIImage * _Nullableimage, NSError * _Nullableerror, SDImageCacheTypecacheType, NSURL * _NullableimageURL) { //生成圆形图片 //开启上下文 UIGraphicsBeginImageContextWithOptions(image.size, NO, 0); //描述裁剪路径 UIBezierPath *path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0, 0, image.size.width, image.size.height)]; //设置裁剪区域 [pathaddClip]; //开始裁剪 [imagedrawAtPoint:CGPointZero]; //获取裁剪后的图片 image = UIGraphicsGetImageFromCurrentImageContext(); //关闭上下文 UIGraphicsEndImageContext(); _imageV.image = image; }]; </code></pre> <p>大致思路就是这样, 还有一些细节的业务逻辑之类的根据实际需要处理好就行.</p> <p>用MVC在日后可以方便地对代码进行维护, 可以达到”哪里出问题,就去找对应的类修改”的效果.</p> <p> </p> <p> </p> <p>来自:http://ios.jobbole.com/90217/</p> <p> </p>