iOS for MVC模式

本文介绍了MVC模式的基本概念,并通过一个简单的示例展示了在iOS应用中如何使用MVC来组织代码。包括控制层、模型层和显示层的详细说明,帮助读者理解这种设计模式在实际开发中的应用。
摘要由CSDN通过智能技术生成

什么是MVC?

MVC逻辑示意图


我们接下来通过MVC模式要实现的界面:

文件夹结构:



自定义视图AppView.xib示意图:



控制层:

"ViewController.h"

//
//  ViewController.m
//
//  Created by Long.
//  Copyright © 2016年 LongChuang. All rights reserved.
//

#import "ViewController.h"
#import "AppData.h"
#import "AppView.h"

@interface ViewController ()

@end

@implementation ViewController

{
    // 用于接收loadAppData从网络解析得到的数据
    // 可以接受可变数组,因为可变数组继承于NSArray
    NSArray * _appData;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    // 1.加载数据
    _appData = [self loadAppData];
    
    // 2.刷新UI
    [self updateUI];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


// 一.第一步加载数据
-(NSArray *)loadAppData
{
    // 1.(获取地址)获取url,得到plist文件的位置
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"apps.plist" withExtension:nil];
    
    // 2.(通过地址下载)通过数组或者字典的url解析方法加载plist文件,
    //  *使用nsarray或者NSDictionary的方法,因为集合类型只有这两种
    NSArray *arr = [NSArray arrayWithContentsOfURL:url];
  
    
    // 3.(定义容器用于保存解压得到的数据)解析plist文件中的内容
    // 定义一个容器,用于接收解压得到的内容,用可变数组就可以,因为可接收oc对象类型的任何数据
    NSMutableArray *arrM = [NSMutableArray array];
    
    // 4.(解压下载得到的压缩包,既未拆封的集合)开始遍历解压,解析下载得到的NSArray中的NSDictionary内容
    for (NSDictionary *dic in arr) {
        // 5.定义一个解压工具(数据层的功能)
        // 解析数据的方法不应该出现在view层,所以应该把解析数据的方法写在model层
        // 既写到appData类的方法中
        // 首先需要创建一个数据层的类对象,并且把解压得到的数据保存到类的属性中去
        // 这里通过调用类方法,在类的方法内部实现了 1.类对象的创建  2.类对象属性的赋值
        // 并且类方法的返回值是当前类的实例对象
        // 这里定义解压工具的原因是,从网络下载得到的数据,要么是字典,要么是数组,不管是什么集合
        // 一般都是提前规定好的,但是里面的key在之后的开发中可能会发生修改或者增加其他key
        // 如果plist文件的内容发生改变,我们只需要修改数据的解压工具即可,降低耦合度,增加联动性
        AppData *app = [AppData appWithDict:dic];
        
        // 6.把解压得到的数据保存到我们事先准备好的容器中
        // 如果我们不通过数据解压工具,那么这里保存的是一个字典
        // 现在arrM中保存的是AppData类对象,而且这些类对象中都有和字典key相对应的属性,并且已经赋值
        [arrM addObject:app];
    }

    // 7.返回从网络加载并且解析后得到的所有数据
    return arrM;
}


// 二.刷新UI界面
-(void)updateUI
{
    // 1.我们可以创建UIButton,UIView
    // 这里创建的是我们自定义的视图,名字叫AppView
    // 通过调用一个类方法来返回自定义视图,不能使用alloc init是因为需要一些操作来找到我们自定义的视图
    // 然后才能初始化,我们把这一系列的操作都封装到了appView的这个类方法中
    AppView *appView = [AppView createAppView];
    
    // 2.这里需要一些计算,来根据生成的个数自动的设置我们生成的AppView应该在什么位置
    // 定义行数,我们规定一行显示3个应用图标,所以这里设置为3
    NSInteger colNum = 3;
    
    // 3.获取自定义视图模板的宽和高
    CGFloat appW = appView.bounds.size.width;
    CGFloat appH = appView.bounds.size.height;
    
    // 4.计算应用图标与手机屏幕的间距:屏幕的宽度-3个应用的宽度,再除以应用个数+1,因为3个应用会有4个间距
    CGFloat margin = (self.view.bounds.size.width - (appW * colNum)) / (colNum + 1);
    
    // 5.根据从网络获取到的数据_appData是一个数组,根据它的长度循环创建自定义视图
    for (NSInteger i = 0 ; i < _appData.count; i++) {
        // (1) 创建自定义的appView视图
         AppView *appView = [AppView createAppView];
        
        // (2) 计算当前的视图属于第几竖列
        NSInteger col = i % colNum;
        
        // (3)计算视图x的位置:左间距margin+(自定义视图的宽+间距margin)*当前第几列竖列
        CGFloat appX = margin + (appW + margin) * col;
        
        // (4)计算当前的视图属于第几横行
        NSInteger row = i / colNum;
        
        // (5)计算视图y的位置:上间距margin+(自定义视图的高+间距margin)*当前第几横行
        CGFloat appY = margin + (appH + margin) * row;

        // (6)x,y,宽和高,都已经计算好了,直接设置生成的视图位置
        appView.frame = CGRectMake(appX, appY, appW, appH);
        
        // (7)给属性appData赋值,使用了set方法,我们在set方法中做了设置
        // _appData[i]是一个数组,我们在从网络拉取数据的时候,就使用的AppData类进行的解析
        // 所以数组中保存的数据不是字典,是AppData类型的,所以这里可以使用_appData[i]进行赋值
        // 赋值的同时通过set方法,修改自定义视图的应用图标和应用名称
        appView.appData = _appData[i];
        
        // (8)把生成的自定义视图添加到view主视图上
        [self.view addSubview:appView];
    }
    
    
}



@end


模型层:

"AppData.h"

//
//  AppData.m
//
//  Created by Long.
//  Copyright © 2016年 LongChuang. All rights reserved.
//

#import "AppData.h"

@implementation AppData


+(instancetype)appWithDict:(NSDictionary *) dict
{
    // 1.创建appData对象,并且将从字典获取的数据赋值给对象的属性
    // 这里使用self创建对象,谁调用谁创建,返回父类
    // 根据多态的特性可知,我们这里定义的是父类AppData类型,但实际创建的是调用此类方法的类对象的类型
    // 如:一个集成AppData的子类调用,那么创建的就是子类类型
    AppData *app = [[self alloc] init];
    
    // 这里用于给类对象的属性赋值,现在假设字典中只有这2个key,我们完全可以手动写入
    // 如果字典中有几百个key,写起来就不那么方便了
    // app.name = dict[@"name"];
    // app.icon = dict[@"icon"];
    
    
    // 所以,所以,所以,可以调用系统自带的方法
    // 可以自动识别app对象中的属性与dict字典中key 并且自动赋值
    // 注意:类对象中的属性名称一定要与字典中的key关键字相同
    [app setValuesForKeysWithDictionary:dict];
    
    // 这里返回类对象,因为类对象中保存了从字典中解析得到的数据,并且赋值给类对象的属性
    // 返回一个属性已经赋值的类对象给view视图
    return app;
}
@end


显示层:

"AppView.h"

//
//  AppView.m
//
//  Created by Long.
//  Copyright © 2016年 LongChuang. All rights reserved.
//

#import "AppView.h"
#import "AppData.h"
@interface AppView()
// 自定义视图中的:应用图标
@property (weak, nonatomic) IBOutlet UIImageView *iconName;
// 自定义视图中的:应用名字
@property (weak, nonatomic) IBOutlet UILabel *contextLabel;
@end


@implementation AppView

// 返回当前自定义视图的类对象
+(instancetype)createAppView
{
    // 这里相当于我们自定义了一个视图,也是UIView类型的,但是我们不想用系统的UIView类型
    // 需要一个自定义的模板
    // 第一步就是找到我们自定义的模板
    // 第二步就是根据模板创建对象
    
    // 1.(找到自定义模板)自定义的视图是xib格式,与代码中UINib是同一个东西,也叫nib
    // 首先需要找到我们自定义的视图nib 这里的@"AppView"不是当前类的名字,是自定义xib的名字AppView.xib
    // bundel设置为nil,就表示使用的是mainBundle
    UINib *nib = [UINib nibWithNibName:@"AppView" bundle:nil];
    
    
    // 2.(通过自定义模板创建对象)通过nib实例化对象
    AppView *appView = [[nib instantiateWithOwner:nil  options:nil]firstObject];
    
    // 3.返回自定义视图对象给方法调用者
    return appView;
}

// 在控制层循环创建视图的时候,把从网络获取的数据复制给这个AppData
-(void)setAppData:(AppData *)appData
{
    // 把网络数据中的应用图片名字和应用程序名字赋值给视图的属性
    _appData = appData;
    self.iconName.image = [UIImage imageNamed:appData.icon];
    self.contextLabel.text = appData.name;
}
@end


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zok93

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值