自定义View控件(手写,xib)须知

 1. 目的 :提高代码的复用性,屏蔽内部的实现细节

2. 步骤
    * 1> 自定义一个类继承于UIView
   * 2> 在initWithFrame方法中添加子控件
   * 3> 在layoutSubviews中设置子控件的位置
   * 4> 提供一个属性保存外界传入的数据(模型对象), 重写setter方法设置子控件的数据
3. 类工厂方法(便利构造器):
   * 按照苹果的风格和规范, 一般情况一个用于创建对象的对象方法会对应一个类方法
   * 可以通过类工厂方法, 快速的根据数据创建一个对象
4. 注意点:
   * 返回值一定要使用instancetype, 不要使用id
   * 在类工厂方法中创建对象, 使用self, 不要使用类名

5. 误区:
/* 1. 手动写代码创建自定义控件,不建议在自定义控件init中设置自定义控件的子控件frame,建议使用 layoutSubviews 方法来设置子控件的位置frame*/

// layoutSubviews方法:专门用于设置子控件的frame

// 比如: ShopView *shopView = [[ShopView alloc] init];
// 后设置 frame,然后你在调用自定义控件的init方法时,自定义控件的frame还没有值,所有子控件无法根据自定义控件的frame来,设置其子控件的frame
shopView.frame = CGRectMake(100, 100, 100, 100);

因为你可能调用init方法时,自定义的控件的frame还没有设置,所有在
自定义的控件的init方法,无法根据父控件位置设置其子控件的位置。

// 解决方案:
所有我们一般重写 - (void)layoutSubviews方法中,设置自定义控件的子控件的位置.
注意:别忘了在layoutSubviews方法中调用[super layoutSubviews];然后设置子控件的frame


/* 2. 子控件设置成weak不会释放,*/

是因为它添加到父控件中,父控件会将其添加到subViews数组中,
数组强引用了它,所有就算设置成weak,还有强指针指向就不会释放.


/* 3. 假如自定义了一个自定义控件,建议使用init初始化自定义控件,而在自定义控件中用 initWithFrame添加自定义控件的子控件:*/

initWithFrame初始化自定义控件,而自定义控件中使用的是init方法添加子控件,这样子控件不会显示出来,
因为调用自定义控件中的initWithFrame方法,不会调用自定义控件中的init方法。

然而如果,自定义控件用init初始化,而自定义控件中用initWithFrame方法添加子控件,这样子控件就会在自定义控件中显示,
因为:初始化自定义控件使用init方法是会调用子控件initWithFrame方法。(调用init方法时,而initWithFrame方法是会在init方法中调用)

/* 4. layoutSubviews方法 */

// layoutSubviews方法:专门用于设置子控件的frame
// layoutSubViews什么时候调用
// 注意:别忘了在layoutSubviews方法中调用[super layoutSubviews];然后设置子控件的frame

1. 第一次创建控件的时候调用
2. 修改了控件的frame时调用
3. 修改位置x,y坐标时不会调用(注)
4. 设置时,控件frame一样时不会调用(注)


/* 5. xib - 》xcode -> User Interface -> empty/View */

1. 什么是xib:xib和storyboard一样都是用来描述界面的
2. xib是storyboard的前身
3. xib是用来描述一个简单的界面或者局部界面
4. storyboard是来描述整体,界面间跳转,全局界面
5. 加载xib的两种方式:

// 1>loadNibNamed
NSArray * res = [[NSBundle mainBundle] loadNibNamed: .... ];
UIView *view = views.firstObject;

// 2> [UINib nibWithName:....]
UINib *nib = [UINib nibWithNme:....];
NSArray *views = [nib instantiateWithOwner...... ];
UIView *view = views.firstObject;

6. 规律: 一般情况下苹果的方法中要求传入一个bundle参数, 直接传nil就代表mainBundle

/* 6. xib创建自定义控件注意点 */

注意:如果是通过xib或者storyboard创建一个控件,不会调用initWithFrame方法,
而是在“创建时”会调用initWithCoder方法,调用该方法时,控件不一定被创建好了,如果我们打算给xib的控件设置属性,不一定会起作用
而在“创建后”会调用aweakFromNib方法,所有我们可以在两个方法中都拿到xib控件设置属性即可。


/* 7. 利用xib创建自定义View 步骤 */

   * 1.新建一个Xib描述界面
   * 2.新建一个继承于Xib界面中父控件类型的类来管理界面
   * 3.在xib中关联界面和类
   * 4.重写awakeFromNib方法, 进行一些初始化
   * 5.提供一个属性保存外界传入的数据(模型对象), 重写setter方法设置子控件的数据

- 注意点:
- 不应该在控制器中加载xib, 应该将加载xib的操作封装到自定义view中

+ (instancetype)shopView
{
return [[[NSBundle mainBundle] loadNibNamed:@"XMGShopView" owner:nil options:nil] firstObject];
}

- 方法的执行顺序
   + 如果是通过xib或者Storyboard创建一个控件, 不会调用initWithFrame方法
   + 在"创建时"会调用initWithCoder方法
         * 控件不一定被创建好了
    + 在"创建后"会调用awakeFromNib
         * 控件一定被创建好了

/* 8. xib启动原理 */

+ 1. 根据custom class创建对象

XMGShopView *shopView = [XMGShopView alloc] init];

+ 2. 根据xib中的设置, 设置控件的相关属性

shopView.backgroundColor = [UIColor redColor];
shopView.frame = CGRectMake(0, 0, 70, 100);

+ 3. 创建所有子控件, 并且设置子控件的属性

UIImageView *iv = [[UIImageView alloc] init];
iv.frame = CGRectMake(0, 0, 70, 70);
UILabel *label = [[UILabel alloc] init];
label.frame = CGRectMake(0, 70, 70, 30);

+ 4. 检查子控件是否有连线, 如果有就进行关联

self.iconView = iv;
self.nameLabel = label;

+ 5.将所有子控件添加到父控件中

[shopView addSubview:iv];
[shopView addSubview:label];
posted @ 2015-07-14 00:34  J了个P  阅读(330)  评论(0编辑  收藏  举报