扯两句 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>