IOS开发基础—通过联系人管理实例学习xib的基本使用

摘要

本文通过一个实例:模拟建立联系人管理app,提供基本的添加和删除联系人功能,来学习xib的基本操作。

xib基本知识总结

  1. 可以认为xib和nib是同义词
  2. 加载xib文件的时候,会创建objects下面的所有控件,并且按顺序装到数组中返回。
  3. storyboard和xib的区别:
    1>区别:
    storyboard:描述软件界面,大范围,重量级,比较适合描述整个软件的所有界面
    xib:描述软件的界面,小范围,轻量级,适合描述某个小界面,局部界面。
    2> 相同点:本质都是代码

  4. file’owner的使用步骤

    在xib文件中设置file’s owner的类属性(目的是在xib中能够找到owner的方法和属性)
    建立file’s owner跟控件的联系
    利用代码加载xib,传递owner参数(类型一定要匹配)。

实例

viewController h代码

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (weak, nonatomic) IBOutlet UIBarButtonItem *delBut;

- (IBAction)addContact:(UIBarButtonItem *)sender;

- (IBAction)delContact:(UIBarButtonItem *)sender;

@end
viewController m代码
//
//  ViewController.m
//  联系人管理—简单的添加删除
//
//  Created by dqw on 15/5/9.
//  Copyright (c) 2015年 itcast. All rights reserved.
//

#import "ViewController.h"
#import "NewContact.h"

#define kDuration 1.0
#define kHeight 30
#define kTag 10
#define kWidth 320

@interface ViewController ()
{
    NSArray *_contNames;
}

@end

@implementation ViewController

- (void)viewDidLoad {

    [super viewDidLoad];
    // 定义联系人名字数组。
    _contNames =  @[@"贾某", @"张某", @"丁某", @"李某"];
}

#pragma mark 1. 定义添加联系人的方法
#pragma mark 重点:重点:如此多的代码都可以被xib来代替。
- (UIView *)addContactM
{
#pragma mark 创建联系人view。
#pragma mark 注意点1:subviews中的元素,要定义一个uiview的指针才能取出其中的属性。
    //     subviews数组的元素默认是id类型的,所以xxsubviews.lastobject.framexx是不被认可的表达。
    //    定义联系人view的位置。
    UIView *lastView = self.view.subviews.lastObject;
    CGFloat newContPosy = lastView.frame.origin.y + lastView.frame.size.height + 1;

//     此处是要创建一个新对象的,要为其分配空间,不能像上面那样仅仅是一个指针。
    UIView *newContact = [[UIView alloc] initWithFrame:CGRectMake(320, newContPosy, kWidth, kHeight)];

    // 设置联系人view。
    newContact.backgroundColor = [UIColor redColor];
    newContact.alpha = 0;

    [self.view addSubview:newContact];

#pragma mark 创建联系人头像
    // 定义头像图片。
    int no = arc4random_uniform(9);
    NSString *imgName = [NSString stringWithFormat:@"01%d.png", no];
    UIImage *contIconImg = [UIImage imageNamed: imgName];

    UIButton *contIcon = [[UIButton alloc]initWithFrame:CGRectMake(5, 0, 30, 30)];
    [contIcon setBackgroundImage:contIconImg forState:UIControlStateNormal];
    [contIcon addTarget:self action:@selector(printContName:) forControlEvents:UIControlEventTouchUpInside];

    [newContact addSubview:contIcon];

#pragma mark 创建联系人名字
    UILabel *contName = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, kWidth, kHeight)];
    no = arc4random_uniform(_contNames.count);
    contName.text = _contNames[no];
    contName.textAlignment = 1;
    contName.tag = kTag;

    [newContact addSubview:contName];

#pragma mark 创建精确删除联系人按钮
    UIButton *delCurBut = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    delCurBut.frame = CGRectMake(280, 0, 30, 30);
    [delCurBut setTitle:@"删除" forState:UIControlStateNormal];
    [delCurBut addTarget:self action:@selector(delCurCont:) forControlEvents:UIControlEventTouchUpInside];
    [newContact addSubview:delCurBut];

    return newContact;
}

#pragma mark 2. 定义打印联系人名字的方法(供头像点击事件调用)
- (void)printContName:(UIButton *)sender
{
#pragma mark 重点1:由view得到兄弟view,不用再@Property成员。
    UILabel *contName = [[sender superview] viewWithTag:kTag];

    //注意类型转换,多态。
    //    NSLog(@"%@", ((UILabel *)[[sender superview] viewWithTag:kTag]).text);

    NSLog(@"%@", contName.text);
}

#pragma mark 3. 监听添加联系人。(单击了添加按钮,按钮就是该方法的调用者)。
- (IBAction)addContact:(UIBarButtonItem *)sender {

#pragma mark 注意点2:设置enabled属性的位置。
    _delBut.enabled = YES;

//    UIView *aContact = [self addContactM];

#pragma mark  重点:重点:体会将xib封装在一个类中的好处。
    NewContact *aContact = [NewContact contactIcon:[NSString stringWithFormat:@"01%d.png", arc4random_uniform(9)] Name:_contNames[arc4random_uniform(4)]];

    UIView *lastView = self.view.subviews.lastObject;
    CGFloat newContPosy = lastView.frame.origin.y + lastView.frame.size.height + 1;
    aContact.frame = CGRectMake(kWidth, newContPosy, kWidth, kHeight);
    [aContact.delBut addTarget:self action:@selector(delCurCont:) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:aContact];

    // 定义动画。
    [UIView animateWithDuration:kDuration animations:^{

        CGRect tempFrame = aContact.frame;
        tempFrame.origin.x = 0;
         aContact.frame = tempFrame;
         aContact.alpha = 1;

    }completion:^(BOOL finished){
    }];

}

#pragma mark 4. 监听删除联系人。
- (IBAction)delContact:(UIBarButtonItem *)sender {

#pragma mark 注意点3:定义在代码块外部,供多个代码块使用。
    UIView *lastView = self.view.subviews.lastObject;
    [UIView animateWithDuration:kDuration animations:^{

    // 如果放在这里,其不能被completion里面的代码调用。
    // UIView *lastView = self.view.subviews.lastObject;

        CGRect tempFrame = lastView.frame;
        tempFrame.origin.x = 320;
        lastView.frame = tempFrame;
        lastView.alpha = 0;

    }completion:^(BOOL finished){

         NSLog(@"1——%d", self.view.subviews.count);
        [lastView removeFromSuperview];
         NSLog(@"2——%d", self.view.subviews.count);

        // 放在这里是正确的。
         _delBut.enabled = (self.view.subviews.count > 1);
    }];
#pragma mark 重点2:体会动画方法中completion里面代码的执行顺序。
    // 该打印是在删除之前,所以下面的判断也是在删除之前,所以判断无效。
     NSLog(@"3——%d", self.view.subviews.count);
   // _delBut.enabled = (self.view.subviews.count > 1);
}

#pragma mark 5. 删除当前联系人。
- (void)delCurCont:(UIButton *)sender
{
#pragma mark 注意点4:进一步体会定义指代指针的位置,与subviews和count对比。
    //因为其在后面使用中没有被改变,索引可用在这里定义,用superView来指代它,但是类似于subviews和count等等,因为下面会对其更改,所以还是使用其本身,以保证值的更新。
    UIView *superView = sender.superview;
    [UIView animateWithDuration:kDuration animations:^{

        CGRect tempF = superView.frame;
        tempF.origin.x = kWidth;
        superView.frame = tempF;
        superView.alpha = 0;

    }completion:^(BOOL finished) {

#pragma mark 注意点5:索引的当前superview的位置,体会代码的位置。
        int curIndex = [self.view.subviews indexOfObject:superView];

        [superView removeFromSuperview];

        [UIView animateWithDuration:0.5 animations:^{

            // 将下面的联系人依次上移。
           for (int i = curIndex; i < self.view.subviews.count; i++) {

                   UIView *tempView = self.view.subviews[i];
                   CGRect tempF = tempView.frame;
                    tempF.origin.y -= kHeight + 1;
                    tempView.frame = tempF;
               }
        }];
        // 继续判断删除的按钮的是否可用。
        _delBut.enabled = self.view.subviews.count > 1;
    }];
}
#pragma mark 重中之重+不解之处:file‘s owner的设置:设置file'owner的话,虽然可以连线,但是运行出错,而view的类属性设为newcontact的话 ,则可以运行。????
@end
newcontact h代码
#import <UIKit/UIKit.h>

@interface NewContact : UIView

#pragma mark 重点1:只有将xib文件中任意一个view的类属性是NewContact,则其中的所有view的类属性默认都是NewContact,就所有的view里面的控件都可以和.h文件里面的属性和方法建立联系。
@property (weak, nonatomic) IBOutlet UIButton *icon;

@property (weak, nonatomic) IBOutlet UILabel *name;

@property (weak, nonatomic) IBOutlet UIButton *delBut;

+ (NewContact *)contactIcon:(NSString *)iconNaem Name:(NSString *)name;

@end
newcontact m代码
#import "NewContact.h"

@implementation NewContact

#pragma mark 1. 将新联系人的创建和部分初始化包装成newcontact的一个类方法。
+ (NewContact *)contactIcon:(NSString *)iconNaem Name:(NSString *)name
{
#pragma mark 重点1:owner的使用,如果xib里面的东西要用到对象方法,则必须要制定确切的owner(是个对象),此处是个类方法,所以可以不用指定owner。
    NewContact *aContact = [[NSBundle mainBundle] loadNibNamed:@"NewContact" owner:nil options:nil][0];

    // 在方便的情况下,能够放在这里初始化的就放在这里初始化。
    aContact.backgroundColor = [UIColor redColor];
    aContact.alpha = 0;

    return aContact;
}
@end

重点 难点 注意点

  1. subviews中的元素默认是id类型的,要定义一个uiview类型的指针指向它,才能间接得到其中元素的属性。
  2. 体会仅仅创建指针指向某一个已存在的对象,和创建一个新对象的使用场合。
  3. 如何有当前view得到其兄弟view,通过父view和tag间接得到,注意类型转换。
  4. 动画方法中completion中的代码,是要在动画执行完毕后采执行,是动画执行的过程中,执行动画后面的代码,动画执行完毕,再返回来执行completion中的代码。
  5. 重中之重+不解之处:file‘s owner的设置:设置file’owner的话,虽然可以连线,但是运行出错,而view的类属性设为newcontact的话 ,则可以运行,此时利用loadnibxx方法返回的对象就是newcontact类型的。
  6. owner的使用,如果xib里面的东西要用到对象方法,则必须要制定确切的owner(是个对象),此处是个类方法,所以可以不用指定owner。
  7. 只有将xib文件中任意一个view的类属性是NewContact,则其中的所有view的类属性默认都是NewContact,所有的view里面的控件都可以和.h文件里面的属性和方法建立联系。
  8. 创建随机数的方法
  9. 类延展的使用,定义供多个方法使用的变量。
  10. xib的sh属性要设置为freeXX类型,才能调整高度。
  11. 本例中需要注意按钮的enabled属性的设置位置(时间),得到subviews中元素或者个数的时间。
  12. 属性后面有animationable修饰的话,说明它是可以添加动画的。

疑问

  1. file’s owner中的owner和loadnibxx里面的owner是不是一回事??
  2. file’owner 的类属性设置为newcontact类后,可以和newcontact。h中的属性和方法连线,但是运行错误。而如果将xib文件的view类属性进行同样的设置的话,则运行正常。
  3. loadnibnamed 里面的owner 究竟指谁?
  4. addtarget里面的target指的又是谁?
  5. viewController里面的self指的又是谁?
  6. uibutton type roundedrect 是不是就是带边框的。我设置的为什么没有边框。老师的例子,放在我这运行,视频的上的边框就没了,估计是软件版本的问题。
  7. 修改名字的两个方法:1. 3出修改,记得setting里面的修改)2. setting里面的修改如果不管用的话,则用删除再添加的方法。试了,没有成功。
  8. bar button item 添加图片,有背景色的图片,添加后都是蓝色的小实心圆,一个红色的x,没有背景色,添加后变成蓝色了。看了它的属性,有image 属性,但是好像没有color相关的。

待完善的内容

  1. 提高调试的能力,仔细分析所出现的错误。如本例中出现的错误有不稳定的特性,就要去怀疑是不是产生随机数处的问题。
  2. 更改名字的方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值