iOS開發基礎-九宮格座標(2)之模型

  在iOS開發基礎-九宮格(1)中,屬性變量 apps 是從plist文件中加載數據的,在 viewDidLoad 方法中的第20行、26行中,直接經過字典的鍵名來獲取相應的信息,使得 ViewController 直接與數據打交道,若是頻繁這樣使用,可能會不當心把鍵名寫錯,而程序卻不會報錯。所以,考慮把字典數據轉換成一個模型,把數據封裝到模型中去,讓 ViewController 與模型交互,而不與數據直接打交道。html

  修改iOS開發基礎-九宮格(1)中的代碼:數組

1、字典轉模型介紹

字典轉模型的好處:app

  1)下降代碼的耦合度;ide

  2)將字典轉模型部分代碼集中在一到處理,下降代碼出錯機率;編碼

  3)程序中,直接對模型的屬性進行操做,提供編碼效率。atom

  4)調用時,沒必要關心模型內部的任何細節。spa

2、代碼實例

  新建一個類命名爲 WJQAppInfo 繼承自 NSObject ,在 WJQAppInfo.h 頭文件中聲明公共的屬性和方法:code

 1 //WJQAppInfo.h,模型類
 2 #import <UIKit/UIKit.h>
 3 
 4 @interface WJQAppInfo : NSObject
 5 @property (nonatomic, copy) NSString *name;     //圖片名稱
 6 @property (nonatomic, copy) NSString *desc;     //圖片信息描述
 7 @property (nonatomic, strong, readonly) UIImage *image;
 8 
 9 - (instancetype)initWithDict:(NSDictionary *)dict;
10 + (instancetype)appInfoWithDict:(NSDictionary *)dict;       //工廠方法
11 @end

  定義屬性時,會自動生成 setter 和 getter 方法,以及一個帶下劃線的成員變量。若是是 readonly 屬性,則只生成 getter 方法,也沒喲成員變量。orm

   instancetype 會讓編譯器檢查實例化對象的準確類型,其只能用於返回類型,不能當作參數使用。htm

   WJQAppInfo 類的實現文件代碼以下:

 1 //WJQAppInfo.m
 2 #import "WJQAppInfo.h"
 3 
 4 @interface WJQAppInfo ()
 5 {
 6     UIImage *_imageABC;
 7 }
 8 @end
 9 
10 @implementation WJQAppInfo
11 
12 - (instancetype)initWithDict:(NSDictionary *)dict {
13     self = [super init];
14     if (self) {
15         self.name = dict[@"name"];
16         self.desc = dict[@"desc"];
17     }
18     return self;
19 }
20 
21 + (instancetype)appInfoWithDict:(NSDictionary *)dict {
22     return [[self alloc] initWithDict:dict];
23 }
24 
25 - (UIImage *)image {
26     if (!_imageABC) {
27         _imageABC = [UIImage imageNamed:self.name];
28     }
29     return _imageABC;
30 }
31 
32 @end

  在 ViewController.m 文件中導入 WJQAppInfo 頭文件。

  修改屬性 apps 的 getter 方法,代碼以下:

 1 //字典轉換成WJQAppInfo模型
 2 - (NSArray *)apps {
 3     if (!_apps) {
 4         NSString *path = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"plist"];
 5         //_apps = [NSArray arrayWithContentsOfFile:path];
 6         NSArray *array = [NSArray arrayWithContentsOfFile:path];
 7         NSMutableArray *arrayM = [NSMutableArray array];
 8         for (NSDictionary *dict in array) {
 9             //遍歷數組,將數據在的字典依次轉化爲WJQAppInfo對象,並添加到臨時對象arrayM中去
10             //用字典來實例化對象的工廠方法
11             [arrayM addObject:[WJQAppInfo appInfoWithDict:dict]];
12         }
13         _apps = arrayM;
14     }
15     return _apps;
16 }

  修改 viewDidLoad 代碼以下:

 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
 3     
 4     int totalColumn = 3;        //3列
 5     CGFloat margin = (self.view.frame.size.width - totalColumn*appViewWidth) / (totalColumn + 1);
 6     int count = self.apps.count;
 7     NSLog(@"%d", count);
 8     
 9     for (int i = 0; i < count; i++) {
10         int row = i/totalColumn;        //行號,從0開始
11         int column = i%totalColumn;     //列號,從0開始
12         CGFloat appViewX = margin + (margin + appViewWidth) * column;       //子視圖的X座標
13         CGFloat appViewY = margin + (margin + appViewHeight) * row;      //子視圖的Y座標
14         
15         //建立UIView控件
16         UIView *appView = [[UIView alloc] initWithFrame:CGRectMake(appViewX, appViewY, appViewWidth, appViewHeight)];
17         [self.view addSubview:appView];
18         //建立上述UIView控件的子視圖,建立圖像信息
19         UIImageView *appImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 80, 50)];
20         WJQAppInfo *appInfo = self.apps[i];
21         UIImage *appImage = appInfo.image;
22         appImageView.image = appImage;      //設置圖片
23         [appImageView setContentMode:UIViewContentModeScaleAspectFit];
24         [appView addSubview:appImageView];
25         //建立上述UIView控件的子視圖,建立UILabel信息描述標籤
26         UILabel *appLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 50, 80, 20)];
27         [appLabel setText:appInfo.desc];    //設置圖片信息描述
28         [appLabel setTextAlignment:NSTextAlignmentCenter];
29         [appLabel setFont:[UIFont systemFontOfSize:12.0]];
30         [appLabel setTextColor:[UIColor blueColor]];
31         [appView addSubview:appLabel];
32         //建立下載按鈕
33         UIButton *appButton = [UIButton buttonWithType:UIButtonTypeCustom];
34         appButton.frame = CGRectMake(0, 70, 80, 20);
35         [appButton setBackgroundImage:[UIImage imageNamed:@"download"] forState:UIControlStateNormal];
36         [appButton setBackgroundImage:[UIImage imageNamed:@"downloaded"] forState:UIControlStateHighlighted];
37         [appButton setTitle:@"下載" forState:UIControlStateNormal];
38         appButton.titleLabel.font = [UIFont systemFontOfSize:12.0];
39         [appButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
40         [appView addSubview:appButton];
41         [appButton addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
42     }
43 }

  使用 KVC 從新寫模型類中的  initWithDict: 方法:

1 //WJQAppInfo.m
2 - (instancetype)initWithDict:(NSDictionary *)dict {
3     self = [super init];
4     if (self) {
5         [self setValue:dict[@"name"] forKey:@"name"];
6         [self setValue:dict[@"desc"] forKey:@"desc"];
7     }
8     return self;
9 }

  或者使用 setValuesForKeysWithDictionary: 方法再對該方法進行修改:

1 //WJQAppInfo.m
2 - (instancetype)initWithDict:(NSDictionary *)dict {
3     self = [super init];
4     if (self) {
5         [self setValuesForKeysWithDictionary:dict];
6     }
7     return self;
8 }

   setValuesForKeysWithDictionary: 方法會遍歷形參 dict 中每一個鍵值調用 setValue:forKey: 方法,可是當字典中有某個鍵值而調用的對象沒有相應的屬性時,系統會崩潰。

 

參考博客:iOS開發UI篇—字典轉模型

實例代碼:http://pan.baidu.com/s/1i4aQTFZ

相關文章
相關標籤/搜索