简单MVC模式demo-应用管理附源码


这是一个应用管理的简单demo 具体效果如下:

demo 使用的知识点如下:

? UIView的常见属性和方法

? 九宫格计算方法

? 字典转模型

? Xib的使用

? 自定义view(view的封装)

? 简单的MVC

 

模型 Mode :  CLApp.m

dict 是一个字典,保存的是应用图标名称,和应用名称

import "CLApp.h"
@interface CLApp ()

@end


@implementation CLApp
-(instancetype)initWithDict:(id)dict
{
    if (self = [super init]) {
        _icon = dict[@"icon"];
        _name = dict[@"name"];
    }
    return self;
}

+ (instancetype)appWithDict:(id)dict
{
    return [[self alloc]initWithDict:dict];
}
@end

 

因为控制器要控制协调模型,视图,所以代码量是最多,整个应用的业务逻辑体现于此.为了能让控制器的代码足够的简洁,清楚,优雅!所以要尽可能的对Mode和View封装.

 

控制器Controller:  CLViewController.m

#import "CLViewController.h"

#import "CLApp.h"
#import "CLAppView.h"

@interface CLViewController ()
/**
 *  存放应用的信息 名称和图标
 */
@property (nonatomic, strong) NSArray *apps;

@end

@implementation CLViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    //1.应用的尺寸
    CGFloat appW = 85;
    CGFloat appH = 90;
    
    //2.列数
    int totalcolumn = 3;
    
    //3.间隙
    CGFloat marginX = (self.view.frame.size.width - totalcolumn * appW) / (totalcolumn + 1);
    CGFloat marginY = 25;
    

    //4.根据应用个数创建对应框框
    for (int index = 0; index < self.apps.count; index++) {
        //4.1计算格子的X和Y
        CGFloat appX = (index % totalcolumn) * (appW + marginX) + marginX;
        CGFloat appY = (index / totalcolumn) * (appH + marginY) + marginY;
        
        //4.2创建appView
        CLAppView *appView = [CLAppView appViewWithApp:self.apps[index]];
        [self.view addSubview:appView];
        
        //4.3设置frame
        appView.frame = CGRectMake(appX, appY, appW, appH);
    }
}

-(NSArray *)apps
{
    //获取主目录
    NSBundle *bundle = [NSBundle mainBundle];
    
    //获取全路径
    NSString *path = [bundle pathForResource:@"app" ofType:@"plist"];
//    //加载数组
//    _apps = [NSArray arrayWithContentsOfFile:path];
    NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
    
    NSMutableArray *appArray = [NSMutableArray array];
    
    for (NSDictionary *dict in dictArray) {
        //CLApp *app = [[CLApp alloc]initWithDict:dict];
        CLApp *app = [CLApp appWithDict:dict];
        
        [appArray addObject:app];
    }
    
    _apps = appArray;
    return _apps;
}

@end

使用Xib文件描述局部界面 如下图:

 

 

视图 View  :CLAppView

#import "CLAppView.h"

@interface CLAppView ()

- (IBAction)btnClick;

@end


@implementation CLAppView
- (void)setApp:(CLApp *)app
{
    _app = app;
    
    //设置图标
    self.iconView.image = [UIImage imageNamed:app.icon];
    
    //2.设置名称
    self.name.text = app.name;
    
    
}

- (instancetype) initWithApp: (CLApp *)app
{
    NSBundle *bundle = [NSBundle mainBundle];
    NSArray *objs = [bundle loadNibNamed:@"CLAppView" owner:nil options:nil];
    
    CLAppView *appView = [objs lastObject];
    
    appView.app = app;
    return appView;
}

+ (instancetype) appViewWithApp: (CLApp *)app
{
    CLAppView *appView = [[CLAppView alloc]initWithApp:app];
    return appView;
}
- (IBAction)btnClick {
    
    CGFloat btnW = 80;
    CGFloat btnH = 20;
    CGFloat btnX = (self.superview.superview.frame.size.width - btnW) * 0.5;
    CGFloat btnY = (self.superview.superview.frame.size.height - btnH) * 0.5;
    _info = [[UILabel alloc]initWithFrame:CGRectMake(btnX, btnY, btnW, btnH)];
    
    _info.text = self.name.text;
    _info.backgroundColor = [UIColor greenColor];
    _info.textAlignment = NSTextAlignmentCenter;
    _info.alpha = 0.7;
    _info.contentMode = UIViewContentModeCenter;
    CGSize infoSize = [_info.text sizeWithFont:_info.font constrainedToSize:CGSizeMake(320, btnH)];
    _info.bounds = CGRectMake(btnX, btnY, infoSize.width, btnH);
    
    
    [UIView animateWithDuration:2 animations:^{
        _info.alpha = 0;
    }];
    
    [self.superview addSubview:_info];

    
}

@end

注意点:

1. 用模型取代字典的好处

? 使用字典的坏处

? 一般情况下,设置数据和取出数据都使用“字符串类型的key”,编写这些key时,编译器不会有任何友善提示,需要手敲

dict[@"name"] = @"Jack";

NSString *name = dict[@"name"];

? 手敲字符串key,key容易写错

? Key如果写错了,编译器不会有任何警告和报错,造成设错数据或者取错数据

? 使用模型的好处

? 所谓模型,其实就是数据模型,专门用来存放数据的对象,用它来表示数据会更加专业

? 模型设置数据和取出数据都是通过它的属性,属性名如果写错了,编译器会马上报错,因此,保证了数据的正确性

? 使用模型访问属性时,编译器会提供一系列的提示,提高编码效率

app.name = @"Jack”;

NSString *name = app.name;

l 字典转模型的过程最好封装在模型内部

l 模型应该提供一个可以传入字典参数的构造方法

- (instancetype)initWithDict:(NSDictionary *)dict;

l + (instancetype)xxxWithDict:(NSDictionary *)dict;

2. instancetype

instancetype在类型表示上,跟id一样,可以表示任何对象类型

instancetype只能用在返回值类型上,不能像id一样用在参数类型上

instancetype比id多一个好处:编译器会检测instancetype的真实类型

3. Xib文件的使用

Xib文件可以用来描述某一块局部的UI界面

Xib文件的加载

? 方法1

NSArray *objs = [[NSBundle mainBundle] loadNibNamed:@"MJAppView" owner:nil options:nil];

这个方法会创建xib中的所有对象,并且将对象按顺序放到objs数组中

(如果xib如右图所示,那么objs数组中依次会有3个对象:1个UIView、1个UIButton、1个UISwitch)

? 方法2

bundle参数可以为nil,默认就是main bundle

UINib *nib = [UINib nibWithNibName:@"MJAppView" bundle:[NSBundle mainBundle]];

NSArray *objs = [nib instantiateWithOwner:nil options:nil];

? 在开发阶段,面向开发者的是xib文件; 当把应用装到手机上时,xib文件就会转为nib文件

4. Xib和storyboard对比

? 共同点:

? 都用来描述软件界面

? 都用Interface Builder工具来编辑

? 不同点

? Xib是轻量级的,用来描述局部的UI界面

? Storyboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系

5. view的封装

如果一个view内部的子控件比较多,一般会考虑自定义一个view,把它内部子控件的创建屏蔽起来,不让外界关心

外界可以传入对应的模型数据给view,view拿到模型数据后给内部的子控件设置对应的数据

简单MVC模式demo-应用管理附源码,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。