一、view封装的思路:

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

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

二、封装控件的基本步骤--四步

  1>添加子控件(子控件也可通过懒加载实现)

  *在initWithFrame:方法中添加子控件,提供便利构造方法  ps--init方法内部会调用initWithFrame:方法,所以说外部调用的时候直接用init调用

 @interface ChaosShopView () // 类扩展,定义子控件成员变量,保证封装性
/** 商品图片 */
@property(nonatomic,strong) UIImageView *thingImg;
/** 商品名称 */
@property(nonatomic,strong) UILabel *thingLabel; @end
 // 步骤一:重写构造方法,定义需要的子控件 init方法内部会自动调用initWithFrame:方法
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor redColor];
// 创建图片
UIImageView *image = [[UIImageView alloc] init];
image.backgroundColor = [UIColor blueColor];
_thingImg = image; // 创建标签
UILabel *label = [[UILabel alloc] init];
label.backgroundColor = [UIColor orangeColor];
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont systemFontOfSize:];
_thingLabel = label; [self addSubview:label];
[self addSubview:image]; }
return self;
}

  2>设置子控件的尺寸

  *在layoutSubviews方法中设置子控件的frame(一定要调用super的layoutSubviews)。不在构造方法中设置子控件尺寸的原因是:子控件的尺寸可能会用到父类的尺寸,在构造函数中父类的frame属性不一定有值,从而导致子控件的frame属性值也会为0。layoutSubviews方法的触发是当父类控件的frame属性发生改变的时候触发!

 // 步骤二:重写layoutSubviews方法,父控件尺寸改变时调用该方法。父控件有了尺寸再设置子控件的尺寸
// 注意的是:一定调用父类的layoutSubviews方法
- (void)layoutSubviews
{
// 一定调用父类的方法
[super layoutSubviews];
// 一般在这个方法里设置子控件的尺寸
CGFloat width = self.frame.size.width;
CGFloat height = self.frame.size.height;
self.thingImg.frame = CGRectMake(, , width, width);
self.thingLabel.frame = CGRectMake(, width, width, height - width);
}

  3>增加模型属性(这个不要定义在扩展类中了,因为外界需要访问传数据),在模型属性set方法中设置数据到子控件上。

 #import <UIKit/UIKit.h>
#import "ShopModel.h" @interface ChaosShopView : UIView /** 数据模型 */
@property(nonatomic,strong) ShopModel *shopModel; // 定义一个类方法
+ (instancetype)shopView; @end
 // 步骤三:定义模型成员变量,重写模型的set方法,为子控件加载数据
-(void)setShopModel:(ShopModel *)shopModel
{
// 先给成员变量赋值,把值存起来
_shopModel = shopModel;
[self.thingImg setImage:[UIImage imageNamed:shopModel.icon]];
self.thingLabel.text = shopModel.name;
}

  4>可以增加一个类方法,实现快捷开发

  声明的代码就不写了,直接写实现的代码吧

+(instancetype)shopView
{
return [[ChaosShopView alloc] init]; // init方法中会调用自己重写的initWithFrame:方法
}

三、创建控件的时候几行代码就搞定

     // 类方法快捷创建
ChaosShopView *shopView = [ChaosShopView shopView];
// 设置尺寸
shopView.frame = CGRectMake(bagX, bagY, bagWidth, bagHeight);
// 数据
shopView.shopModel = shopModel;

iOS边练边学--view的封装的更多相关文章

  1. iOS边练边学--图片的拉伸

    图片拉伸方法一: IOS 5.0以后才有的方法: - (void)viewDidLoad { [super viewDidLoad]; UIImageView *imageView = [[UIIma ...

  2. iOS边练边学--父子控件之作为导航控制器的子类产生的问题以及网易新闻练习

    一.导航控制器的子类 作为导航控制器的子类,并且是导航控制器子类中的第一个,系统会默认给子控件添加EdgeInsert属性,把导航栏的宽度挤出来.但是系统只会默认修改第一个. 解决办法1:系统帮忙给第 ...

  3. iOS边练边学--CALayer,非根层隐式动画,钟表练习

    一.CALayer UIView之所以能显示在屏幕上,完全是因为他内部的一个图层 在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性 ...

  4. iOS边练边学--xib文件初使用

    一.Xib和storyboard对比 *共同点: 1>都用来描述软件界面 2>都用Interface Builder工具来编辑 3>本质都是转换成代码去创建控件 *不同点 1> ...

  5. iOS边练边学--NSURLSession、NSURLSessionTask的介绍与使用以及url中包含了中文的处理方法

    一.NSURLSession.NSURLSessionTask的使用步骤 首先创建NSURLSession对象 通过NSURLSession对象创建对应的任务 <1>NSURLSessio ...

  6. iOS边练边学--Http网络再学习,简单介绍

    一.URL 什么是URL URL中常见的协议 二.Http Http的基本通信过程 发送Http请求的方法 GET 和 POST 对比 GET 和 POST 的选择 三.iOS中的Http学习 iOS ...

  7. iOS边练边学--多线程练习的多图片下载 以及 使用第三方框架(SDWebImage)的多图片下载

    一.自己实现多图片下载应该注意的问题 沙盒缓存的问题 程序缓存的问题 cell重复利用显示图片混乱的问题 -- 用户拖拽快,下载图片慢导致的 解决图片混乱引入NSOperation集合的问题 资源下载 ...

  8. iOS边练边学--多线程NSOperation介绍,子类实现多线程的介绍(任务和队列),队列的取消、暂停(挂起)和恢复,操作依赖与线程间的通信

    一.NSOperation NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加 ...

  9. iOS边练边学--多线程介绍、NSThread的简单实用、线程安全以及线程之间的通信

    一.iOS中的多线程 多线程的原理(之前多线程这块没好好学,之前对多线程的理解也是错误的,这里更正,好好学习这块) iOS中多线程的实现方案有以下几种 二.NSThread线程类的简单实用(直接上代码 ...

随机推荐

  1. Linux中断 - 驱动申请中断API

    一.前言 本文主要的议题是作为一个普通的驱动工程师,在撰写自己负责的驱动的时候,如何向Linux Kernel中的中断子系统注册中断处理函数?为了理解注册中断的接口,必须了解一些中断线程化(threa ...

  2. C# list介绍

    一.LIST概述 所属命名空间:System.Collections.Generic      public class List<T> : IList<T>, ICollec ...

  3. Python之反射练习

    # 什么是反射?可以用字符串的方式去访问对象的属性 class Test(): _name = "sss" def fun(self): return "Hellowor ...

  4. C++中虚基类在派生类中的内存布局

    今天重温C++的知识,当看到虚基类这点的时候,那时候也没有太过追究,就是知道虚基类是消除了类继承之间的二义性问题而已,可是很是好奇,它是怎么消除的,内存布局是怎么分配的呢?于是就深入研究了一下,具体的 ...

  5. openstack_swift源代码分析——Swift单机部署

    本文对在单机部署swift 当中每个细节做具体的介绍,并对配置做对应的解释 PC物理机    Ubuntu-12.04-desktop-64位 Swift 版本号:1.13.1 Swift-clien ...

  6. vim:修改光标的显示

    我比较习惯vim下光标显示为一条竖线,这样的好处是可以准确的知道光标的位置.但有的时候光标表现为一个方块.这个是可以修改改地. 终端下: 终端下这个和终端的光标设置有关,只要修改了终端中光标的显示,v ...

  7. Python并发编程实例教程

    有关Python中的并发编程实例,主要是对Threading模块的应用,文中自定义了一个Threading类库. 一.简介 我们将一个正在运行的程序称为进程.每个进程都有它自己的系统状态,包含内存状态 ...

  8. wpf程序线程与UI内容交互

    在UI线程里执行复杂的操作,会造成UI假死.常用的解决方法是开2个线程. 而新线程要调用UI里的东西,必须这么用: this.Dispatcher.Invoke(content);

  9. C#使用CodeDom动态加载cs文件

    public static object Create(string path) { var provOptions = new Dictionary<string, string>(); ...

  10. rabbitmq 常用的一些命令

    rabbitmqctl set_user_tags admin administrator #给用户设置角色 rabbitmqctl set_permissions -p emove admin &q ...