UIView之基础控件综合事例
九宫格算法实现及优化
2015年11月19日 星期四
23:21
1.九宫格之初实现
要求:
1.1在主界面中,点击添加按钮就能添加商品,点击删除按钮就能删除商品;
1.2在初始化界面中,添加按钮处于norma状态,删除按钮处于disable状态;
1.3当点击了添加按钮后,删除按钮此时处于normal状态;
1.4当商品满了后,添加按钮处于disable状态,删除按钮处于normal状态;
1.5当商品为空或者满了的时候给出提示语;
算法思路实现:
1.界面的实现:分析要用到的控件,此需求中,用到了一个view(主控件)和(内部的子控件)一个imageView,两个lable(显示title和hub),两个button(添加和删除按钮).
2.因为要对按钮和view实现操作,所以对其进行引用(获得对应的属性和删除添加操作).
3.导入相对应的图片.
4.在addProduct方法中:
4.1依次创建shopView(父控件),用于加载imageView和title,并添加到主控件中;
3.1.1分别创建imageView和title并设置frame加载到shopView中
4.2此时就需要考虑到加载的商品个数,所以引入商品的信息,用字典存储,并获得index.
4.3在定义frame的时候,考虑到程序中的魔鬼数字,就需要定义一些常量.
4.4加载字典中的icon和name并赋值给相对应的控件imageView和title.
4.5判断按钮的状态,并对enable属性进行相应的设置
5.在removeProduct方法中:
5.1调用[self.shopView.su'b'viewsubviews lastObject]removeFromSuperviews删除商品
5.2判断按钮的状态,并对enable属性进行相应的设置
2.九宫格实现之(字典)懒加载优化
懒加载:
作用:节省内存,当数据字典被使用时候才去使用.防止了在viewDidLoad的时候耗费内存和时间.
实现:首先就得在声明语句中声明一个数组用来保存字典中的数据.
步骤:
懒加载的步骤
1.定义成员变量
2.重写get方法
3.在get方法中判断,变量是否有值,如果没有值,则加载数据,如果有值,直接返回
- (NSArray *)products
{
if (_products == nil) {
_products = @[
@{@"icon" : @"liantiaobao", @"title" : @"链条包"},
@{@"icon" : @"shoutibao", @"title" : @"手提包"},
@{@"icon" : @"danjianbao", @"title" : @"单肩包"},
@{@"icon" : @"shuangjianbao", @"title" : @"双肩包"},
@{@"icon" : @"xiekuabao", @"title" : @"斜挎包"},
@{@"icon" : @"qianbao", @"title" : @"钱包"}
];
}
return _products;
}
3.九宫格实现之(plist文件)懒加载优化
plist懒加载:
- 3.1什么是plist文件
- 直接将数据直接写在代码里面,不是一种合理的做法。如果数据经常改,就要经常翻开对应的代码进行修改,造成代码扩展性低
- 因此,可以考虑将经常变的数据放在文件中进行存储,程序启动后从文件中读取最新的数据。如果要变动数据,直接修改数据文件即可,不用修改代码
- 一般可以使用属性列表文件存储NSArray或者NSDictionary之类的数据,这种“属性列表文件”的扩展名是plist,因此也称为“plist文件”
- 3.2创建plist文件

3.3解析plist文件
- 接下来通过代码来解析Plist文件中的数据
- 获得Plist文件的全路径
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:@"shops" ofType:@"plist"];
- 加载plist文件
_shops = [NSArray arrayWithContentsOfFile:path];
3.4plist的使用注意

3.5如何使用懒加载
- 接下来通过代码来解析Plist文件中的数据
- 获得Plist文件的全路径
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:@"shops" ofType:@"plist"];
- 加载plist文件
_shops = [NSArray arrayWithContentsOfFile:path];
或者可以写成:
_shops = [NSArray arrayWithContentsOfFile:[NSBundle mainBundle]pathForResource:@"shops" ofType:@"plist"]];
4.九宫格实现之模型优化
4.1模型取代字典的好处:
- 使用字典的坏处
- 一般情况下,设置数据和取出数据都使用“字符串类型的key”,编写这些key时,编辑器没有智能提示,需要手敲
dict[@"name"] = @"Jack";
NSString *name = dict[@"name"];
- 手敲字符串key,key容易写错
- Key如果写错了,编译器不会有任何警告和报错,造成设错数据或者取错数据
- 使用模型的好处
- 所谓模型,其实就是数据模型,专门用来存放数据的对象,用它来表示数据会更加专业
- 模型设置数据和取出数据都是通过它的属性,属性名如果写错了,编译器会马上报错,因此,保证了数据的正确性
- 使用模型访问属性时,编译器会提供一系列的提示,提高编码效率
app.name = @"Jack";
NSString *name = app.name;
4.2.实现:
4.2.1.创建一个类模型,并声明相应的属性,用来取代字典,给相应的子控件赋值
4.2.2在懒加载中实现下面的方法:
// 问题:_products数组中存放的都是字典,字典在实际开发使用起来并不是方便
// 3.将字典转成模型对象
NSMutableArray *tempArray = [NSMutableArray array];
for (NSDictionary *dict in _products) {
// 3.1.创建模型对象
Product *product = [[Product alloc] init];
// 3.2.给模型对象的属性赋值
product.icon = dict[@"icon"];
product.title = dict[@"title"];
// 3.3.将模型对象放入数组中
[tempArray addObject:product];
}
_products = tempArray;
4.2.3用模型取代字典进行赋值
// 2.6.设置展示的数据
XMGProduct *product = self.products[index];
iconView.image = [UIImage imageNamed:product.icon];
titleLabel.text = product.title;
4.2.4考虑到在懒加载遍历数组的时候,每次创建XMGProduct的时候都得进行赋值,所以就在模型类中提供初始化方法,使得每次创建的模型对象都有对应的属性:
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
self.icon = dict[@"icon"];
self.title = dict[@"title"];
}
return self;
}
+ (instancetype)productWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
在懒加载时进行修改:
// 3.将字典转成模型对象
NSMutableArray *tempArray = [NSMutableArray array];
for (NSDictionary *dict in _products) {
XMGProduct *product = [XMGProduct productWithDict:dict];
// 3.2.将模型对象放入数组中
[tempArray addObject:product];
}
_products = tempArray;
}
5.九宫格实现之添加控件优化
5.1作用:
在UIController中需要每次创建一个shopView,然后添加到主控件view中,所以我们可以自定义控件来取代这种做法.
5.2控件的实现:
首先就是创建一个对应的类XMGProductView,在类中分别声明对应的属性iconView和titleLable,然后重写init类方法;因为无法在init方法中设置frame,所以就必须重写layoutSubviews方法
- (instancetype)init
{
if (self = [super init]) {
// 1.添加UIImageView对象用于显示商品的图片
UIImageView *iconView = [[UIImageView alloc] init];
[self addSubview:iconView];
_iconView = iconView;
// 2.添加UILabel对象用于显示商品的名字
UILabel *titleLabel = [[UILabel alloc] init];
titleLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:titleLabel];
_titleLabel = titleLabel;
}
return self;
}
- (void)layoutSubviews
{
//注意:必须调用super方法
[super layoutSubviews];
// 1.取出当前控件的宽度和高度
CGFloat width = self.frame.size.width;
CGFloat height = self.frame.size.height;
// 2.调整子控件的frame
self.iconView.frame = CGRectMake(0, 0, width, width);
self.titleLabel.frame = CGRectMake(0, width, width, height - width);
}
考虑到在自定义控件的时候,如果在.h文件中设置对应的属性,那么外界就能通过set和get方法进行修改,为了不让外界修改属性的值,所以必须重写对应的set方法,并统一提供接口.
#pragma mark - 实现接口的方法
- (void)setIcon:(NSString *)iconName
{
self.iconView.image = [UIImage imageNamed:iconName];
}
- (void)setTitle:(NSString *)title
{
self.titleLabel.text = title;
}
在addProduct的方法中,在创建控件并设置数据
/**************** 2.添加商品的View *****************************/
// 1.创建商品的View
XMGProductView *productView = [[XMGProductView alloc] init];
productView.frame = CGRectMake(x, y, width, height);
[self.shopCartView addSubview:productView];
// 2.设置数据
XMGProduct *product = self.products[index];
[productView setIcon:product.icon];
[productView setTitle:product.title];
考虑到为了更加的安全(不让外界了解具体的实现方法),所以又提供了对应的模型方法,只让外界知道模型
- (void)setProduct:(XMGProduct *)product
{
_product = product;
// 设置数据
self.iconView.image = [UIImage imageNamed:product.icon];
self.titleLabel.text = product.title;
}
在addProduct的方法中,在创建控件并设置数据
/********************2.添加商品的View *****************************/
// 1.创建商品的View
XMGProductView *productView = [[XMGProductView alloc] init];
productView.frame = CGRectMake(x, y, width, height);
[self.shopCartView addSubview:productView];
// 2.设置数据
productView.product = self.products[index];
6.九宫格实现之xib优化
6.1Xib和storyboard对比
- 共同点:
- 都用来描述软件界面
- 都用Interface Builder工具来编辑
- 本质都是转换成代码去创建控件
- 不同点
- Xib是轻量级的,用来描述局部的UI界面
- Storyboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系
6.2xib的加载
- 方法1
NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"xib文件名" owner:nil options:nil]
- 方法2
UINib *nib = [UINib nibWithNibName:@"xib文件名" bundle:nil];
NSArray *views = [nib instantiateWithOwner:nil options:nil];
6.3步骤:


6.4注意点
- 一个控件有2种创建方式
- 通过代码创建
- 初始化时一定会调用initWithFrame:方法
- 通过xib\storyboard创建
- 初始化时不会调用initWithFrame:方法,只会调用initWithCoder:方法
- 初始化完毕后会调用awakeFromNib方法
- 有时候希望在控件初始化时做一些初始化操作,比如添加子控件、设置基本属性
- 这时需要根据控件的创建方式,来选择在initWithFrame:、initWithCoder:、awakeFromNib的哪个方法中操作
xib界面的设置:

用xib取代自定义控件的.h文件
#import <UIKit/UIKit.h>
@class XMGProduct;
@interface XMGProductView : UIView
// 快速创建类方法
+ (instancetype)productView;
// 提供模型接口
@property (nonatomic, strong) XMGProduct *product;
@end
用xib取代自定义控件的.m文件
#import "XMGProductView.h"
#import "XMGProduct.h"
@interface XMGProductView ()
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@end
@implementation XMGProductView
+ (instancetype)productView
{
return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil] firstObject];
}
- (void)setProduct:(XMGProduct *)product
{
_product = product;
// 给子控件设置数据
self.iconView.image = [UIImage imageNamed:product.icon];
self.titleLabel.text = product.title;
}
@end
在addProduct的方法中,在创建控件并设置数据
/*********************2.添加商品的View *****************************/
// 1.创建商品的View
XMGProductView *productView = [XMGProductView productView];
productView.frame = CGRectMake(x, y, width, height);
[self.shopCartView addSubview:productView];
// 2.设置数据
productView.product = self.products[index];
7.九宫格实现之提示框动画效果优化
考虑到add和remove的提示框的内容除了提示语不同外,其他的都一样,所以就把提示方法抽取出来简洁代码:
注意:hubLabel为view中的提示框的属性
- (void)showHubInfo:(NSString *)hubInfo
{
// 3.1.改变指示器上面显示的文字
self.hubLabel.text = hubInfo;
// 3.2.出现动画和消失动画
[UIView animateWithDuration:1.0 animations:^{
self.hubLabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:1.0 delay:2.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.hubLabel.alpha = 0.0;
} completion:nil];
}];
}
在addProduct的方法中,调用该方法
/************** 4.购物车已满,给用户提示 *************************/
if (self.shopCartView.subviews.count == 6) {
[self showHubInfo:@"购物车已满,不要买买买啦!"];
}
在removeProduct的方法中,调用该方法
// 3.购物车已空,给用户提示
if (self.shopCartView.subviews.count == 0) {
[self showHubInfo:@"购物车已空,赶紧买买买啦!"];
}
UIView之基础控件综合事例的更多相关文章
- [iOS基础控件 - 5.5] 代理设计模式 (基于”APP列表"练习)
A.概述 在"[iOS基础控件 - 4.4] APP列表 进一步封装,初见MVC模式”上进一步改进,给“下载”按钮加上效果.功能 1.按钮点击后,显示为“已下载”,并且不 ...
- React Native环境搭建以及几个基础控件的使用
之前写了几篇博客,但是没有从最基础的开始写,现在想了想感觉不太合适,所以现在把基础的一些东西给补上,也算是我从零开始学习RN的经验吧! 一.环境搭建 首先声明一下,本人现在用的编辑器是SublimeT ...
- UIView上的控件使用push方法跳转
有时候在项目中,为了保持前后页面的推进方式跳转方式一致,会在通过UIview上的控件跳到另一个Controller上,所以,这时候就需要用到这种方式了,当然,present方法可以实现跳转但是样式可能 ...
- Cocos2d-JS项目之二:studio基础控件的使用
在studio里把几个基础控件往场景文件一拖,然后导出json格式的资源文件 逻辑代码如下: var HelloWorldLayer = cc.Layer.extend({ sprite:null, ...
- [iOS基础控件 - 6.6] 展示团购数据 自定义TableViewCell
A.需求 1.头部广告 2.自定义cell:含有图片.名称.购买数量.价格 3.使用xib设计自定义cell,自定义cell继承自UITableViewCell 4.尾部“加载更多按钮”,以及其被点击 ...
- [iOS基础控件 - 4.5] 猜图游戏
A.需要掌握的 1.添加图片资源(暂时认为@2x跟非@2x代表同一张图片) 2.搭建UI界面* 文本标签* 4个按钮* 中间的图片 3.设置状态栏样式 4.监听下一题按钮的点击 5.延迟加载数据* 加 ...
- [iOS基础控件 - 1] UI概念
A. UIView 1.概念 属于UIKit框架 屏幕上能看得见摸得着的东西就是UIView,比如屏幕上的按钮.文字.图片 翻译为:视图/控件/组件 UIBut ...
- Delphi一共封装(超类化)了8种Windows基础控件和17种复杂控件
超类化源码: procedure TWinControl.CreateSubClass(var Params: TCreateParams; ControlClassName: PChar); con ...
- Cocos2d-JS studio基础控件的使用
在studio里把几个基础控件往场景文件一拖,然后导出json格式的资源文件 逻辑代码如下: 1 var HelloWorldLayer = cc.Layer.extend({ 2 sprite:nu ...
随机推荐
- 【spring】non-compatible bean definition of same name and class
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected excep tion parsing XML do ...
- Linux中ftp不能上传文件/目录的解决办法
在linux中不能上传文件或文件夹最多的问题就是权限问题,但有时也不一定是权限问题了,像我就是空间不够用了,下面我来总结一些ftp不能上传文件/目录的解决办法 在排除用户组和权限等问题后,最可能引 ...
- [Hibernate] - mysql
Hibernate使用mysql例子: 1) 新建一个bean: User.java package com.my.bean; import java.util.Date; public class ...
- Python基础教程【读书笔记】 - 2016/7/10
希望通过博客园持续的更新,分享和记录Python基础知识到高级应用的点点滴滴! 第五波:第1章 基础知识 [总览] 介绍如何得到所需的软件,然后讲一点点算法及其主要的组成.学习变量variable ...
- VoLTE、呼叫等待(保持)
VoLTE 的出现是手机通话的革命,VoLTE带来更好通话质量,更快的接通时间,接近0掉线这些特点,还可以一边通话一边上网,一方面VoLTE需要运营商的支持,另外一方面也需要手机终端的支持. 什么手机 ...
- Excel定位对象(按钮等)
手头只有2003,2007应该类似首先显示控件工具箱,进入设计模式.然后按Ctrl+G,在定位条件里选对象,确定.此时所有空间即被选中,按del可删除之.
- SQL语句技巧_索引的优化_慢查询日志开启_root密码的破解
1.正则表达式的使用 regexp例:select name,email from t where email regexp '@163[.,]com$'使用like方式查询selct name,em ...
- TSP(旅行者问题)——动态规划详解(转)
1.问题定义 TSP问题(旅行商问题)是指旅行家要旅行n个城市,要求各个城市经历且仅经历一次然后回到出发城市,并要求所走的路程最短. 假设现在有四个城市,0,1,2,3,他们之间的代价如图一,可以存成 ...
- ant中copy操作学习心得(转)
Ant真是太方便了,以前都没注意到它.功能很强大,能创建数据库,配置服务器,部署发布应用……只需要写好build.xml文件,剩下的就交给ant来“安装”你的WEB应用了. Appfuse的第一个an ...
- Linux 2.6 内核实时性分析 (完善中...)
经过一个月的学习,目前对linux 下驱动程序的编写有了入门的认识,现在需要着手实践,编写相关的驱动程序. 因为飞控系统对实时性有一定的要求,所以先打算学习linux 2.6 内核的实时性与任务调 ...