*:first-child {
margin-top: 0 !important; }
body > *:last-child {
margin-bottom: 0 !important; }
a {
color: #4183C4; }
a.absent {
color: #cc0000; }
a.anchor {
display: block;
padding-left: 30px;
margin-left: -30px;
cursor: pointer;
position: absolute;
top: 0;
left: 0;
bottom: 0; }
h1, h2, h3, h4, h5, h6 {
margin: 20px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
cursor: text;
position: relative; }
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA09pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoMTMuMCAyMDEyMDMwNS5tLjQxNSAyMDEyLzAzLzA1OjIxOjAwOjAwKSAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUM2NjlDQjI4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUM2NjlDQjM4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5QzY2OUNCMDg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5QzY2OUNCMTg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsQhXeAAAABfSURBVHjaYvz//z8DJYCRUgMYQAbAMBQIAvEqkBQWXI6sHqwHiwG70TTBxGaiWwjCTGgOUgJiF1J8wMRAIUA34B4Q76HUBelAfJYSA0CuMIEaRP8wGIkGMA54bgQIMACAmkXJi0hKJQAAAABJRU5ErkJggg==) no-repeat 10px center;
text-decoration: none; }
h1 tt, h1 code {
font-size: inherit; }
h2 tt, h2 code {
font-size: inherit; }
h3 tt, h3 code {
font-size: inherit; }
h4 tt, h4 code {
font-size: inherit; }
h5 tt, h5 code {
font-size: inherit; }
h6 tt, h6 code {
font-size: inherit; }
h1 {
font-size: 28px;
color: black; }
h2 {
font-size: 24px;
border-bottom: 1px solid #cccccc;
color: black; }
h3 {
font-size: 18px; }
h4 {
font-size: 16px; }
h5 {
font-size: 14px; }
h6 {
color: #777777;
font-size: 14px; }
p, blockquote, ul, ol, dl, li, table, pre {
margin: 15px 0; }
hr {
background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x 0 0;
border: 0 none;
color: #cccccc;
height: 4px;
padding: 0;
}
body > h2:first-child {
margin-top: 0;
padding-top: 0; }
body > h1:first-child {
margin-top: 0;
padding-top: 0; }
body > h1:first-child + h2 {
margin-top: 0;
padding-top: 0; }
body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child {
margin-top: 0;
padding-top: 0; }
a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
margin-top: 0;
padding-top: 0; }
h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
margin-top: 0; }
li p.first {
display: inline-block; }
li {
margin: 0; }
ul, ol {
padding-left: 30px; }
ul :first-child, ol :first-child {
margin-top: 0; }
dl {
padding: 0; }
dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px; }
dl dt:first-child {
padding: 0; }
dl dt > :first-child {
margin-top: 0; }
dl dt > :last-child {
margin-bottom: 0; }
dl dd {
margin: 0 0 15px;
padding: 0 15px; }
dl dd > :first-child {
margin-top: 0; }
dl dd > :last-child {
margin-bottom: 0; }
blockquote {
border-left: 4px solid #dddddd;
padding: 0 15px;
color: #777777; }
blockquote > :first-child {
margin-top: 0; }
blockquote > :last-child {
margin-bottom: 0; }
table {
padding: 0;border-collapse: collapse; }
table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0; }
table tr:nth-child(2n) {
background-color: #f8f8f8; }
table tr th {
font-weight: bold;
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }
table tr td {
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }
table tr th :first-child, table tr td :first-child {
margin-top: 0; }
table tr th :last-child, table tr td :last-child {
margin-bottom: 0; }
img {
max-width: 100%; }
span.frame {
display: block;
overflow: hidden; }
span.frame > span {
border: 1px solid #dddddd;
display: block;
float: left;
overflow: hidden;
margin: 13px 0 0;
padding: 7px;
width: auto; }
span.frame span img {
display: block;
float: left; }
span.frame span span {
clear: both;
color: #333333;
display: block;
padding: 5px 0 0; }
span.align-center {
display: block;
overflow: hidden;
clear: both; }
span.align-center > span {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: center; }
span.align-center span img {
margin: 0 auto;
text-align: center; }
span.align-right {
display: block;
overflow: hidden;
clear: both; }
span.align-right > span {
display: block;
overflow: hidden;
margin: 13px 0 0;
text-align: right; }
span.align-right span img {
margin: 0;
text-align: right; }
span.float-left {
display: block;
margin-right: 13px;
overflow: hidden;
float: left; }
span.float-left span {
margin: 13px 0 0; }
span.float-right {
display: block;
margin-left: 13px;
overflow: hidden;
float: right; }
span.float-right > span {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: right; }
code, tt {
margin: 0 2px;
padding: 0 5px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px; }
pre code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent; }
.highlight pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px; }
pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px; }
pre code, pre tt {
background-color: transparent;
border: none; }
sup {
font-size: 0.83em;
vertical-align: super;
line-height: 0;
}
* {
-webkit-print-color-adjust: exact;
}
@media screen and (min-width: 914px) {
body {
width: 854px;
margin:0 auto;
}
}
@media print {
table, pre {
page-break-inside: avoid;
}
pre {
word-wrap: break-word;
}
}
-->
前言:这个小实例项目是完完全全以MJ视频传授的优化方案一步一个思路从零开始敲出代码的,而且每一步都有思路,都有逻辑所以然。敲代码讲究思路,我个人不建议记忆太多东西,反正我记性很差的。
小贴士:文章末尾有 项目资源 的百度云下载链接。
小实例项目--添加商品和商品名
好,现在完成了 plist文件的数据 --转换到--> 集合对象存储这些数据 ,接下来根据MVC的原则,我们当然需要一个Model(数据模型),所以需要新建数据模型类:
到这里MVC中的Model准备好了,接着就要准备View了:
为了能够将控件给多个控制器共享
- 继承自系统自带的控件,写一个属于自己的控件
- 目的:封装控件内部的细节,不让外界关心
- 步骤:
- 新建一个继承UIView的类
- 在init方法中添加子控件
- 在layoutSubViews方法中设置子控件的frame
- 一定要调用[super layoutSubView]
- 提供一个模型属性(我个人发现:其实可以直接通过初始化方法传入局部参数,然后局部就使用这个模型属性),重写模型属性的set方法
- 在set方法中取出模型属性,给对应的子控件赋值
因为继承自UIView,所以就具有UIView的属性。
比如frame属性,比如addSubView方法,以及可以重写专门用来布局子控件的layoutSubViews方法
layoutSubviews这个方法专门用来布局子控件,设置子控件的frame
-(void)layoutSubviews
{
//这个方法必须要实现
[super layoutSubviews];
}
思考一下自定义控件在这个MVC综合项目应该怎么去自定义和使用:
1、首先因为组合模式,所以需要内部创建两个需要组合的控件:
UIImageView和UILabel这两个子控件。
2、在什么地方创建这两个组合的控件呢?
在初始化方法中创建最合适。因为我们需要一创建这个自定义控件,就创建好了两个子控件。
3、另外,创建子控件需要模型数据model,因为一个UIImageView对应一个icon,一个UILabel对应一个商品名称,
而一个icon和一个UILabel是存储在一个model模型对象中的,所以,还需要创建一个模型对象的引用。
九宫格算法思路:
逻辑过程描述:每点击一次,添加一次图片,而且一行添加超过三次会换行,而且所占位置是父控件的行距离的三分之一。
需要解决问题细分三点:
1、每点击一次,添加一次图片
2、一行添加超过三次换行
3、所在位置是父控件行距离的三分之一
问题1解决思路:每点击一次,变化的是子控件添加1,所以可以通过父控件的子控件数来获取动态数据数值 n :
int n = (int)self.shopsBoxView.subView.count
问题2解决思路:只要涉及到换行可以考虑求余数或者求模:
//行数:row 列:column
int row = n / 3;
int column = n % 3;
然后是九宫格的这个格子的坐标
(0,0)(0,1)(0,2)
(1,0)(1,1)(1,2)
(2,0)(2,1)(2,2)
结合对应子控件的个数的次第
1,2,3
4,5,6
7,8,9
- 简单讲解一下逻辑关系,当我们第一次添加子控件之前,子控件个数count = 0,对应即将添加子控件的坐标是(0,0),所以:count = 0 -> (0,0);count = 1 -> (0,1);count = 2 -> (0,2)...以此类推
总结:用当前子控件个数,通过求得行列的算法,就能算出对应的九宫格格子的坐标
问题3的解决思路:
通过问题二获取的坐标可以对应算出各需要添加的子控件坐标位置。
上代码算法思路(另外直接写完了按钮在数量达到目标数值会自动变成disEnable状态):
1 #import "ViewController.h" 2 #import "HYShopModel.h" 3 #import "HYUIView.h" 4 5 @interface ViewController () 6 7 @property (weak, nonatomic) IBOutlet UIView *shopsBoxView; 8 9 /** 存储数据的引用 */ 10 @property (nonatomic,strong)NSMutableArray *shopsArray; 11 12 /** shopView的宽 */ 13 @property (nonatomic,assign)CGFloat viewWidth; 14 /** shopView的高 */ 15 @property (nonatomic,assign)CGFloat viewHeight; 16 /** 宽间距 */ 17 @property (nonatomic,assign)CGFloat spaceWidth; 18 /** 高间距 */ 19 @property (nonatomic,assign)CGFloat spaceHeight; 20 21 @property (weak, nonatomic) IBOutlet UIButton *addBtn; 22 @property (weak, nonatomic) IBOutlet UIButton *removeBtn; 23 24 @end 25 26 @implementation ViewController 27 28 /** 29 * 重写_shopsArray的get方法 30 * 31 * @return NSMutableArray shosArray 32 */ 33 -(NSMutableArray *)shopsArray{ 34 if (_shopsArray == nil) { 35 36 _shopsArray = [NSMutableArray array]; 37 38 NSString* dataFilePath = [[NSBundle mainBundle] pathForResource:@"shopList.plist" ofType:nil]; 39 40 NSMutableArray* dataArray = [NSMutableArray arrayWithContentsOfFile: dataFilePath]; 41 42 for (NSDictionary *dic in dataArray) { 43 HYShopModel * model = [HYShopModel shopModel:dic]; 44 [_shopsArray addObject:model]; 45 } 46 } 47 return _shopsArray; 48 } 49 50 - (void)viewDidLoad { 51 [super viewDidLoad]; 52 53 [self loadData]; 54 } 55 /** 56 * 加载必要的数值 57 */ 58 -(void)loadData 59 { 60 //抽取重复使用的必要的数值 61 //shopView的宽高 62 _viewWidth = 70; 63 _viewHeight = 100; 64 //间隔距离 65 _spaceWidth = (self.shopsBoxView.frame.size.width - _viewWidth * 3) * 0.5; 66 _spaceHeight = (self.shopsBoxView.frame.size.height - _viewHeight * 3) * 0.5; 67 NSLog(@"%f,%f",_spaceWidth,_spaceHeight); 68 NSLog(@"%f",self.shopsBoxView.frame.size.height); 69 70 } 71 - (IBAction)add { 72 NSLog(@"添加商品展示"); 73 74 75 //shopsBoxView当前子控件的个数 76 int n = (int)self.shopsBoxView.subviews.count; 77 //行数:row 列:column 78 int row = n % 3; 79 int column = n / 3; 80 NSLog(@"row:%d and column:%d",row,column); 81 82 83 84 HYShopModel* model = self.shopsArray[n]; 85 NSLog(@"%@",model); 86 NSLog(@"%@",model.name); 87 HYUIView* shopView = [[HYUIView alloc] initWithShopModel:model]; 88 shopView.frame = CGRectMake(row * _spaceWidth + row * _viewWidth, 89 column * _spaceHeight + column * _viewHeight, 90 _viewWidth, 91 _viewHeight); 92 93 [self.shopsBoxView addSubview:shopView]; 94 95 self.addBtn.enabled = (self.shopsBoxView.subviews.count < 6); 96 self.removeBtn.enabled = (self.shopsBoxView.subviews.count > 0); 97 98 } 99 - (IBAction)remove { 100 NSLog(@"去除商品展示"); 101 //这里需要设置,如果没有商品,就应该取消按钮的可点击状态 102 [self.shopsBoxView.subviews.lastObject removeFromSuperview]; 103 self.removeBtn.enabled = (self.shopsBoxView.subviews.count != 0); 104 self.addBtn.enabled = (self.shopsBoxView.subviews.count < 6); 105 } 106 107 @end
以上错误更正:九宫格算法的代码行数应该是75~92行。
然后回到HYUIView类中,进行最后的优化。
到这里,纯代码最优的项目代码就完成了,其实如果用xib文件的话,会让整个项目开发更简单而且更完美,下一博文进行在这个项目的基础上分解xib的使用以及如果优化这个项目,最后让你感觉到开发IOS真的很爽。
纯代码源文件下载链接: http://pan.baidu.com/s/1qW3TNu0 密码: ymhc
纯代码资源文件下载链接:http://pan.baidu.com/s/1dDsKQ7B 密码: 1squ