扯兩句 MVC 的設計模式
一個app開發的主要流程可以簡單概括為:
搭建UI界面—> 請求服務器數據 —> 把數據展示在UI界面上 –> 處理UI界面的業務邏輯 —> 測試及優化
在編程世界里面大家都知道一句話: 高內聚,低耦合
-
高內聚,就是指盡量讓一個類或者一個方法它專門去處理一個事情,對外只提供一個接口,內部具體如何實現不需要告訴外界.
-
低耦合,就是減少類與類之間相互的依賴性,降低代碼的入侵性,當改變一個類中的一個東西時候,不需要另一個類中也大批量改.
我們在請求網絡數據的時候,通常服務器給我們返回都是json或者xml數據,我們利用第三方框架將它解析之后會得到一個 字典數組 .
這時候如果我們面向字典來開發:
1.這樣不太符合我們 面向對象 開發的偉大思想覺悟
2.由于xcode的原因,在敲字典的key時候系統是不會給我們提示(也就是自動聯想功能)的,這樣容易造成我們有時候不小心敲錯了一個key導致加載不出數據,但是系統又不會報錯,代碼一多很可能就要花很多時間去找八哥(bug),專業點來講就是 容錯率低 .
所以為了順應社會主義發展的步伐,我們需要將 字典數組 轉換為 模型數組 ,也就是將字典轉為模型, 這就要扯到MVC這個設計模式了.
MVC是三個單詞的首字母縮寫, 他們分別是 , 他們分別是, 分別是Model, View, Controller, 也就是模型, 視圖, 控制器.
-
Model : 繼承NSObject, 負責保存數據.
-
View : 視圖控件, 通常用xib來描述它里面的子控件,負責將數據展示在UI界面上
-
Controller : 控制器,負責請求及處理網絡數據, 處理用戶交互
他們三兄弟的關系如下:
這樣子,他們三個各司其職, 符合我們高內聚,低耦合的思想.
下面用簡單的table view實例來闡述一下MVC的使用,如下圖的效果
誰能教教我用markdown放入圖片怎么設置圖片大小?
1.在Model(也叫Item)里面定義屬性,用來保存網絡數據
#import
@interface tagItem : NSObject
@property(nonatomic,strong)NSString *image_list;
@property(nonatomic,strong)NSString *sub_number;
@property(nonatomic,strong)NSString *theme_name;
@end
2.在Controller里面,請求數據,用第三方框架把數據轉化成模型存進Model這個類中, 然后給cell的item屬性賦值,這樣子就可以把item(數據)傳進View里面——簡單的說,就是在Controller里面把數據傳進View里面
//發送網絡請求
-(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];
}];
}
#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;
}
3.在View里面描述好xib,
然后定義item這個屬性,并把各子控件拖好線,
重寫item這個屬性的getter方法(因為在控制器中給item屬性賦值時候就會調用這個方法), 在這個setter方法中用這個item的各個屬性來給View的子控件賦值, 達到把數據展示在UI界面上的目的—簡單來說就是在View里面拿到Model數據,把數據展示在View上
#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;
}];
大致思路就是這樣, 還有一些細節的業務邏輯之類的根據實際需要處理好就行.
用MVC在日后可以方便地對代碼進行維護, 可以達到”哪里出問題,就去找對應的類修改”的效果.
來自:http://ios.jobbole.com/90217/