模型的应用 && Xib &&代理模式的应用【应用管理】
来源:互联网 发布:劫持刘嘉玲的是谁知乎 编辑:程序博客网 时间:2024/04/29 18:35
模型
模型取代字典的好处
- 使⽤用字典的坏处
- ⼀一般情况下,设置数据和取出数据都使⽤用“字符串类型的key”,编写这些key时,编译器不会有任何友善提示,需要手敲。例如:
dict[@"name"] = @"Jack";
NSString *name = dict[@"name"];
- 手敲字符串key,key容易写错 。Key如果写错了,编译器不会有任何警告和报错,造成设错数据或者取错数据。
- ⼀一般情况下,设置数据和取出数据都使⽤用“字符串类型的key”,编写这些key时,编译器不会有任何友善提示,需要手敲。例如:
- 使⽤用模型的好处
- 所谓模型,其实就是数据模型,专门⽤用来存放数据的对象,⽤用它来表⽰示数据会更加专业。
- 模型设置数据和取出数据都是通过它的属性,属性名如果写错了,编译器会马上报错,因此,保证了数据的正确性。
- 使⽤模型访问属性时,编译器会提供一系列的提⽰,提⾼编码效率。例如:
app.name = @"Jack”;
NSString *name = app.name;
字典转模型
- 字典转模型的过程最好封装在模型内部
- 模型应该提供⼀一个可以传⼊入字典参数的构造⽅方法
-(instancetype)initWithDict:(NSDictionary*)dict;
+(instancetype)xxxWithDict:(NSDictionary*)dict;
- instancetype在类型表⽰上,跟id一样,可以表示任何对象类型
instancetype只能用在返回值类型上,不能像id一样用在参数类型上
instancetype比id多一个好处:编译器会检测instancetype的真实类型
构建一个模型类 App 来存储数据
// App.h// 模型类:用来存放数据的类#import <Foundation/Foundation.h>@interface App : NSObject// 模型的名称@property (nonatomic, copy) NSString *name;// 模型的图标@property (nonatomic, copy) NSString *icon;// 通过字典来初始化模型对象- (instancetype) initWithDict:(NSDictionary *)dict;+ (instancetype) appWithDict:(NSDictionary *)dict;@end
// App.m#import "App.h"@implementation App- (instancetype)initWithDict:(NSDictionary *)dict{ if(self = [super init]){ self.name = dict[@"name"]; self.icon = dict[@"icon"]; } return self;}+ (instancetype)appWithDict:(NSDictionary *)dict{ return [[self alloc] initWithDict:dict];}@end
字典转模型的过程
Xib文件
Xib的创建及使用
- Xib文件可以用来描述某一块局部的UI界⾯
- 如何创建Xib文件
- 首先创建一个继承UIView的自定义view。假如这个类叫:APPView。
- 新建一个AppView.xib文件来描述AppView内部的结构。修改UIView的类型为AppView真实类型,即把AppView.xib文件的class 改成 AppView如下图所示:
Xib文件的加载
- 调用方法
NSArray *objs = [[NSBundle mainBundle] loadNibNamed:@"AppView" owner:nil
options:nil]; - 这个方法会创建xib中的所有对象,并且将对象按顺序放到objs数组中。
如果xib如下图所⽰,那么objs数组中依次会有3个对象:1个UIView、1个UILabel、1个UIButton - 在开发阶段,面向开发者的是xib文件; 当把应用装到⼿机上时,xib⽂件就会转为nib⽂件
使用xib封装一个自定义view的步骤
- 调用方法
- 1> 新建一个继承UIView的自定义view,假设类名叫做(AppView)
- 2> 新建一个AppView.xib文件来描述MJAppView内部的结构
- 3> 修改UIView的类型为AppView真实类型
- 4> 将内部的子控件跟AppView进行属性连线
- 5> AppView中创建一个模型属性
- 6> 重写模型属性的set方法,因为在set方法中可以拿到外界传递的模型数据
- 7> 把模型数据拆开,分别设置数据到对应的子控件中
8> 补充:提供一个创建MJAppView的类方法,将读取xib文件的代码屏蔽起来
Xib和storyboard对比
- 共同点:
- 都用来描述软件界面
- 都用Interface Builder⼯具来编辑
- 不同点
- Xib是轻量级的,用来描述局部的UI界面
- Storyboard是重量级的,用来描述整个软件的多个界面,并且能展⽰多个界面之间的跳转关系
源码
结构框架
代码
// ViewController.h//#import <UIKit/UIKit.h>@interface ViewController : UIViewController@end
//// ViewController.m//#import "ViewController.h"#import "AppView.h"#import "App.h"@interface ViewController () <AppViewDelegate>@property (nonatomic, strong) NSArray *apps;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; // 添加应用信息 // 1.总列数(一行最多3列) int totalColumns = 3; // 2.应用的尺寸 CGFloat appW = 90; CGFloat appH = 90; // 3.间隙 = (控制器view的宽度 - 3 * 应用宽度) / 4 CGFloat marginX = (self.view.frame.size.width - totalColumns * appW) / (totalColumns + 1); CGFloat marginY = 40; // 4.根据应用个数创建对应的框框(index 0 ~ 11) for(int index = 0 ; index < self.apps.count; index++){ // 3.1 创建view,设置数据 AppView *appView = [AppView appViewWithApp:self.apps[index]]; // 3.2 把view的代理设置为控制器 appView.delegate = self; // 3.3 添加view [self.view addSubview:appView]; // 3.4 设置frame int row = index / totalColumns; int col = index % totalColumns; // 计算x和y CGFloat appX = marginX + col * (appW + marginX); CGFloat appY = 40 + row * (appH + marginY); appView.frame = CGRectMake(appX, appY, appW, appH); }}// 点击下载按钮时就会调用- (void)appViewClickedDownloadButton:(AppView *)appView{ // 1.取出模型 App *app = appView.app; // 添加标签 UILabel *tipLabel = [[UILabel alloc] init]; tipLabel.text = [NSString stringWithFormat:@"下载成功%@", app.name]; tipLabel.font = [UIFont systemFontOfSize:14]; tipLabel.textAlignment = NSTextAlignmentCenter; tipLabel.textColor = [UIColor whiteColor]; tipLabel.backgroundColor = [UIColor blackColor]; tipLabel.frame = CGRectMake(0, 0, 170, 40); tipLabel.center = CGPointMake(187.5, 300); tipLabel.alpha = 0.0; tipLabel.layer.cornerRadius = 5; tipLabel.clipsToBounds = YES; [self.view addSubview:tipLabel]; // 3.动画 [UIView animateWithDuration:1.0 animations:^{ tipLabel.alpha = 0.5; } completion:^(BOOL finished) { [UIView animateWithDuration:1.0 delay:1.0 options:UIViewAnimationOptionCurveLinear animations:^{ tipLabel.alpha = 0.0; } completion:^(BOOL finished) { [tipLabel removeFromSuperview]; }]; }];}- (NSArray *)apps{ if(_apps == nil){ // 初始化 // 1.获得plist的全路径 NSString *path = [[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil]; // 2.加载数组 NSArray *dictArray = [NSArray arrayWithContentsOfFile:path]; // 3.将dictArray里面的所有字典转成模型对象,放到新的数组中 NSMutableArray *appArray = [NSMutableArray array]; for(NSDictionary *dict in dictArray){ // 3.1 创建模型对象 App *app = [App appWithDict:dict]; // 3.2 添加模型对象到数组中 [appArray addObject:app]; } // 4.赋值 _apps = appArray; } return _apps;}@end
//// App.h// 模型类:用来存放数据的类#import <Foundation/Foundation.h>@interface App : NSObject// 模型的名称@property (nonatomic, copy) NSString *name;// 模型的图标@property (nonatomic, copy) NSString *icon;// 通过字典来初始化模型对象- (instancetype) initWithDict:(NSDictionary *)dict;+ (instancetype) appWithDict:(NSDictionary *)dict;@end
//// App.m//#import "App.h"@implementation App- (instancetype)initWithDict:(NSDictionary *)dict{ if(self = [super init]){ self.name = dict[@"name"]; self.icon = dict[@"icon"]; } return self;}+ (instancetype)appWithDict:(NSDictionary *)dict{ return [[self alloc] initWithDict:dict];}@end
//// AppView.h//#import <UIKit/UIKit.h>@class App, AppView;// 声明一个协议@protocol AppViewDelegate <NSObject>@optional- (void)appViewClickedDownloadButton:(AppView *)appView;@end@interface AppView : UIView// 代理@property (nonatomic, weak) id<AppViewDelegate> delegate;// 数据模型@property (nonatomic, strong) App *app;// 创建模型+ (instancetype)appView;//通过模型数据来创建一个view+ (instancetype)appViewWithApp:(App *)app;@end
//// AppView.m//#import "AppView.h"#import "App.h"@interface AppView()@property (weak, nonatomic) IBOutlet UIImageView *iconView;@property (weak, nonatomic) IBOutlet UILabel *nameLabel;- (IBAction)download:(UIButton *)sender;@end@implementation AppView+ (instancetype)appViewWithApp:(App *)app{ NSBundle *bundle = [NSBundle mainBundle]; // 读取xib文件(会创建xib中的描述的所有对象,并且按顺序放到数组中返回) NSArray *objs = [bundle loadNibNamed:@"AppView" owner:nil options:nil]; AppView *appView = [objs lastObject]; appView.app = app; return appView;}+ (instancetype)appView{ return [self appViewWithApp:nil];}- (void)setApp:(App *)app{ _app = app; // 1.设置图标 self.iconView.image = [UIImage imageNamed:app.icon]; // 2.设置名称 self.nameLabel.text = app.name;}// 下载按钮- (IBAction)download:(UIButton *)sender { // 1.让按钮失效(文字变为“已下载”) sender.enabled = NO; [sender setTitle:@"已下载" forState:UIControlStateDisabled]; // 2.通知代理,download按钮被点击。 if([self.delegate respondsToSelector:@selector(appViewClickedDownloadButton:)]){ [self.delegate appViewClickedDownloadButton:self]; }}@end
代理模式
为什么要用代理模式
- 我们要拿到控制器View,然后让它显示tipLabel,但是怎么拿到控制器View?
- (1)将控制器View传到AppView.m里面,然后在download:方法调用,但这种方法非常不好,耦合性太强。
- (2) 将按钮抛出去(放在AppView.h里面,这样控制器也可以监听),让控制器View监听,这样也不好。
- 正确的方法是用代理模式,控制器作为AppView的代理。
对代理模式的分析
- 当点击下载按钮的时候,应该通知控制器,控制器得知点击了下载按钮,就执行:添加tipLabel到控制器的View
- 该做的事情应该交给该做的那个类去做(比较适合谁做的事情,就交给谁去做)。比如说我们要拿到控制器的view,添加一个label,谁能直接拿到控制器的view,就是控制器。所以我们得到一个结论,拿到控制器,添加lable的代码(操作),应该放到控制器里面。
- 控制器要监听【AppView】内部下载按钮的点击,当下载按钮被点击了,会到download:方法,我们要在download:方法里面通知控制器(代理)(
[self.delegate appViewClickedDownloadButton:self];
这个方法就是通知代理),下载按钮被点击,然后控制器把label添加到它的view上面上去。
达到效果
- 点击下载按钮后变成不能点击的“已安装”
- 中间慢慢弹出提⽰示:已经成功安装xxx,然后提⽰示会慢慢消失
0 0
- 模型的应用 && Xib &&代理模式的应用【应用管理】
- 代理模式的应用
- “代理模式”的应用
- xib文件的应用
- ios-day07-01(使用xib自定义cell、UITableView的footerView“点击加载更多”、headerView为UIScrollView、代理模式的应用)
- 接口的实际应用--代理设计模式
- JAVA学习--接口的应用:代理模式
- 协议的应用—代理设计模式
- 商店应用的进程模型 -- 管理App
- Proxy代理的应用
- 动态代理的应用
- 6.2 代理的应用
- storyboard 和xib的本地化的应用
- Java代理模式 动态代理 的应用场景
- 代理模式-Java动态代理的实现及应用
- Java代理模式 动态代理 的应用场景
- select模型的应用
- 语素模型的应用
- java学习总结之IO
- shell之logger
- 让IE6 IE7 IE8 IE9 IE10 IE11支持Bootstrap的解决方法
- springmvc中针对一个controller方法配置两个url请求
- cocoaPods使用细节
- 模型的应用 && Xib &&代理模式的应用【应用管理】
- [机器学习]机器学习之数学知识回顾-矩阵及优化理论
- 问题解决:FFmpeg视频编解码库,无法解析的外部信号
- 改变体质,预防癌症第一步 (分享大家学习)
- 换手率短线炒股神器测评
- 尾递归
- java编程思想(读书笔记):8.接口和内隐类
- linux 设置共享目录
- 平台开发中访问窗体其他属性