UI基础

2018-03-04  本文已影响0人  恒筠

第一节

1.UI控件中拖线属性或方法常见错误

经典的错误
   1. 错误一
    描述:
      reason: '[<MainViewController 0x7ffebbc1a880> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key testLabel.'
    原因: 有多余的连线
    解决: 删除多余的连线
 
   2.错误二
    描述:
      reason: '-[MainViewController clickBtn:]: unrecognized selector sent to instance 0x7feb69418640'
    原因:找不到对应的方法
    解决:1.添加对应的方法  2.删除多余的连线

2.UIView的常见属性

第二节

1.UIImageView的frame的设置

 // 设置frame的方式
    // 方式一
      UIImageView *imageView = [[UIImageView alloc] init];
      imageView.image = [UIImage imageNamed:@"1"];
     
//    imageView.frame = CGRectMake(100, 100, 267, 400);
//    imageView.frame = (CGRect){{100, 100},{267, 400}};
    */
    
    // 方式二
    /*
    UIImageView *imageView = [[UIImageView alloc] init];
    // 创建一个UIImage对象
    UIImage *image = [UIImage imageNamed:@"1"];
    // 设置frame
    imageView.frame = CGRectMake(100, 10, image.size.width, image.size.height);
    // 设置图片
    imageView.image = image;
     */
    
    // 方式三
    /*
    // 创建一个UIImage对象
    UIImage *image = [UIImage imageNamed:@"1"];
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 10, image.size.width, image.size.height)];
    imageView.image = image;
     */
    
    // 方式四
    
    // 创建一个UIimageview对象
    // 注意: initWithImage 默认就有尺寸--->图片的尺寸
    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"1"]];
    
    // 改变位置
//    imageView.center = CGPointMake(200, 150);
    
    imageView.center = CGPointMake(self.view.frame.size.width * 0.5, self.view.frame.size.height * 0.5);

2.控件的创建方式

注意:
有时候希望在控件初始化时做一些初始化操作,比如添加子控件、设置基本属性
这时需要根据控件的创建方式,来选择在initWithFrame:、initWithCoder:、awakeFromNib的哪个方法中操作

3.xib的加载

方法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];

4.加载图片的方式

  1. imageNamed:与
  2. imageWithContentsOfFile:的区别
图片的两种加载方式:
1> imageNamed:
  a. 就算指向它的指针被销毁,该资源也不会被从内存中干掉
  b. 放到Assets.xcassets的图片,默认就有缓存
  c. 使用场景:图片经常被使用

2> imageWithContentsOfFile:
  a. 指向它的指针被销毁,该资源会被从内存中干掉
  b. 放到项目中的图片就没有缓存
  c. 使用场景:不经常用,大批量的图片

5.Xcode插件大全

第三节

1.九宫格

第四节

1.懒加载

1.作用:
1>用到的时候再加载
2>全局只会被加载一次
3>全局都可以使用

过程:
1.重写成员变量的get方法
2.在get方法中判断:
1>如果为空,加载数据
2>如果不为空,就直接返回数据

第五节

1.自定义控件与模型

* 首先在自定义控件的.m文件中重写initwithframe方法,在这个方法中创建控件

* 然后再laysubview方法中给控件设置尺寸

* 在.h文件中设置一个模型属性,然后在.m文件中充血模型属性的set方法,把传递进来的模型属性的值设置给对应控件

为自定义控件充血init 和 类工厂方法,

2.自定义按钮

注意: 在按钮外面改的尺寸,按钮的内部都会覆盖掉

    /*
    button.titleLabel.frame = CGRectMake(0, 0, 100, 70);
    button.imageView.frame = CGRectMake(100, 0, 70, 70);
     */

正确的做法

[button titleRectForContentRect:CGRectMake(0, 0, 100, 70)];
[button imageRectForContentRect:CGRectMake(100, 0, 70, 70)];


如果需要改变按钮控件内部的图片和label的frame的话又两种方法

一个是重写按钮内部的layoutsubview方法
另外一个是重写按钮内部的

3.图片的拉伸问题


  UIImage *resizableImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(imageHeight * 0.5, imageWidth * 0.5, imageHeight * 0.5 -1, imageWidth * 0.5 - 1)];
  

另外的一个方法

//    UIImage *resizableImage = [image stretchableImageWithLeftCapWidth:imageWidth * 0.5 topCapHeight:imageHeight * 0.5];

4.KVC

>1.利用KVC进行简单赋值

在简单赋值过程中会进行自动类型转换比如

[person setValue:@"19" forKeyPath:@"money"]; 
NSLog(@"%@-----%.2f", person.name, person.money)

打印结果整形转成浮点型

>2.KVC综合赋值

 forKey和forKeyPath
 1>forKeyPath 包含了所有 forKey 的功能
 2>forKeyPath 进行内部的点语法,层层访问内部的属性
 3>注意: key值一定要在属性中找到

>3.利用KVC修改类的私有成员变量

利用KVC修改类的私有成员变量

4.字典转模型

作用: 字典转模型
开发中是不建议使用setValuesForKeysWithDictionary:
1> 字典中的key必须在模型的属性中找到
2> 如果模型中带有模型,setValuesForKeysWithDictionary不好使
应用场景: 简单的字典转模型 ---> 框架 (MJExtention)

5.取值

6.把模型转成字典

   NSDictionary *dict = [person dictionaryWithValuesForKeys:@[@"name", @"money"]];

7.取出数组中所有模型的某个属性值

        XMGPerson *person1 = [[XMGPerson alloc] init];
        person1.name = @"zhangsan";
        person1.money = 12.99;
        
        XMGPerson *person2 = [[XMGPerson alloc] init];
        person2.name = @"zhangsi";
        person2.money = 22.99;
        
        XMGPerson *person3 = [[XMGPerson alloc] init];
        person3.name = @"wangwu";
        person3.money = 122.99;
        
        NSArray *allPersons = @[person1, person2, person3];
        NSArray *allPersonName = [allPersons valueForKeyPath:@"name"];
        
        NSLog(@"%@", allPersonName);

5KVO

KVO: Key Value Observing (键值监听)--->当某个对象的属性值发生改变的时候(用KVO监听)

    /*
     作用:给对象绑定一个监听器(观察者)
     - Observer 观察者
     - KeyPath 要监听的属性
     - options 选项(方法方法中拿到属性值)
     */
    [person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    
    
    person.name = @"ls";
    
    person.name = @"ww";
    

    
    // 移除监听
    [person removeObserver:self forKeyPath:@"name"];

注意增加监听的时候记得移除监听,就好像添加通知要移除通知一样

增加监听以后可以在observeValueForKeyPath这个方法中监听到属性值的改变

第六节

1.监听scrollView各种行为的3大步骤(比如让控制 器监听scrollView的行为)

scrollView.delegate = 控制器;

  
@interface 控制器 () <UIScrollViewDelegate> @end
 
 
#pragma mark - <UIScrollViewDelegate> 代理 法
{
NSLog(@"scrollViewDidScroll-滚动"); }

2.代理使用的一般规律

3.如何监听控件的行为

4.NSTimer的使用

 @property (nonatomic, weak) NSTimer *timer;
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
 // 返回 个 动开始执 任务的定时器
 
 self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self
 
// NSDefaultRunLoopMode(默认): 同一时间只能执行一个任务
// NSRunLoopCommonModes(公用): 可以分配一定的时间执行其他任务
// 作用:修改timer在runLoop中的模式为NSRunLoopCommonModes
// 目的:不管主线程在做什么操作,都会分配一定的时间处理定时器
  [self.timer invalidate];

5.UIScrollView

1.基本使用

2.常见属性

3.偏移量和内边距

4.监听scrollView的各种行为

如何监听scrollView已经停止滚动 有2种情况
第一种手松开,scrollView就停止滚动 第二种,用户停止拖拽,但scrollView由于惯性继续滚动,并且减速

5.内容缩放

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;
* 设置minimumZoomScale 
* 设置maximumZoomScale   

跟缩放相关的其他代理方法
即将开始缩放的时候调用

正在缩放的时候调用

第七节

1.Autolayout

+(id)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
view1 :要约束的控件
attr1 :约束的类型(做怎样的约束)
relation :与参照控件之间的关系
view2 :参照的控件
attr2 :约束的类型(做怎样的约束)
multiplier :乘数
c :常量

[图片上传失败...(image-cbf8ee-1520169654402)]

在添加时要注意目标view需要遵循以下规则:

[图片上传失败...(image-42483c-1520169654402)]

[图片上传失败...(image-dea5d5-1520169654402)]

[图片上传失败...(image-f2d463-1520169654402)]

[UIView animateWithDuration:1.0 animations:^{
    [添加了约束的view的父控件 layoutIfNeeded];
}];

2.VFL语言实现autolayout

使用VFL来创建约束数组
+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;
format :VFL语句
opts :约束类型
metrics :VFL语句中用到的具体数值
views :VFL语句中用到的控件

创建一个字典(内部包含VFL语句中用到的控件)的快捷宏定义
NSDictionaryOfVariableBindings(...)

3.Masonry目前最流行的autolayout的第三方kuangjia

默认情况下
mas_equalTo有自动包装功能,比如自动将20包装为@20
equalTo没有自动包装功能

如果添加了下面的宏,那么mas_equalTo和equalTo就没有区别
#define MAS_SHORTHAND_GLOBALS
// 注意:这个宏一定要添加到#import "Masonry.h"前面

默认情况下
width是make对象的一个属性,用来添加宽度约束用的,表示对宽度进行约束
mas_width是一个属性值,用来当做equalTo的参数,表示某个控件的宽度属性

如果添加了下面的宏,mas_width也可以写成width
#define MAS_SHORTHAND

mas_height、mas_centerX以此类推

第八节

1.���UITableView

注意:在开发中等号左右两边的类型要是同一类型

2.UITableViewCell

UITableViewCell重用


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 1.定义一个cell的标识
      static NSString *ID = @”cell";
    
    // 2.从缓存池中取出cell
      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    
    // 3.如果缓存池中没有cell
      if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }

注意:tableview和tableviewcell有一个共同的特点就是他们一创建出来就已经确定了样式,在接下去的代码中用访问属性的点语法也改不了他们的样式

第九节

1.在UITableview中自定义等高cell

新建一个继承自UITableViewCell的子类,比如XMGTgCell

@interface XMGTgCell : UITableViewCell
@end

在XMGTgCell.m文件中

/**
 *  在这个方法中添加所有的子控件
 */
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        // ......
    }
    return self;
}
/**
 *  在这个方法中计算所有子控件的frame
 */
- (void)layoutSubviews
{
    [super layoutSubviews];

    // ......
}

在XMGTgCell.h文件中提供一个模型属性,比如XMGTg模型

@class XMGTg;

@interface XMGTgCell : UITableViewCell
/** 团购模型数据 */
@property (nonatomic, strong) XMGTg *tg;
@end

在XMGTgCell.m中重写模型属性的set方法

- (void)setTg:(XMGTg *)tg
{
    _tg = tg;

    // .......
}

在控制器中

[self.tableView registerClass:[XMGTgCell class] forCellReuseIdentifier:ID];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 访问缓存池
    XMGTgCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    // 设置数据(传递模型数据)
    cell.tg = self.tgs[indexPath.row];

    return cell;
}

2.在UITableview中自定义不登高的cell

给模型增加frame数据

@interface XMGStatus : NSObject
/**** 文字\图片数据 ****/
// .....

/**** frame数据 ****/
/** 头像的frame */
@property (nonatomic, assign) CGRect iconFrame;
// .....
/** cell的高度 */
@property (nonatomic, assign) CGFloat cellHeight;
@end
- (CGFloat)cellHeight
{
    if (_cellHeight == 0) {
        // ... 计算所有子控件的frame、cell的高度
    }
    return _cellHeight;
}

在控制器中

/**
 *  返回每一行cell的具体高度
 */
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    XMGStatus *status = self.statuses[indexPath.row];
    return status.cellHeight;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 访问缓存池
    XMGStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    // 设置数据(传递模型数据)
    cell.status = self.statuses[indexPath.row];

    return cell;
}

新建一个继承自UITableViewCell的子类,比如XMGStatusCell

@interface XMGStatusCell : UITableViewCell
@end

在XMGStatusCell.m文件中

/**
 *  在这个方法中添加所有可能需要显示的子控件
 */
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        // ......
    }
    return self;
}

在XMGStatusCell.h文件中提供一个模型属性,比如XMGStatus模型

@class XMGStatus;

@interface XMGStatusCell : UITableViewCell
/** 微博模型数据 */
@property (nonatomic, strong) XMGStatus *status;
@end

在XMGStatusCell.m中重写模型属性的set方法

- (void)setStatus:(XMGStatus *)status
{
    _status = status;

    // .......
}

重写-layoutSubviews方法

/**
 *  在这个方法中设置所有子控件的frame
 */
- (void)layoutSubviews
{
    [super layoutSubviews];

    // ......
}




3自定义不等高的cell 使用storyboard

对比自定义等高cell,需要几个额外的步骤(iOS8开始才支持)

// 告诉tableView所有cell的真实高度是自动计算(根据设置的约束来计算)
self.tableView.rowHeight = UITableViewAutomaticDimension;
// 告诉tableView所有cell的估算高度
self.tableView.estimatedRowHeight = 44;

如果要支持iOS8之前

- (void)awakeFromNib
{
    // 手动设置文字的最大宽度(目的是:让label知道自己文字的最大宽度,进而能够计算出自己的frame)
    self.text_label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
}
// 告诉tableView所有cell的估算高度(设置了估算高度,就可以减少tableView:heightForRowAtIndexPath:方法的调用次数)
self.tableView.estimatedRowHeight = 200;
XMGStatusCell *cell;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 创建一个临时的cell(cell的作用:根据模型数据布局所有的子控件,进而计算出cell的高度)
    if (!cell) {
        cell = [tableView dequeueReusableCellWithIdentifier:ID];
    }

    // 设置模型数据
    cell.status = self.statuses[indexPath.row];

    return cell.height;
}

- (CGFloat)height
{
    // 强制布局cell内部的所有子控件(label根据文字多少计算出自己最真实的尺寸)
    [self layoutIfNeeded];

    // 计算cell的高度
    if (self.status.picture) {
        return CGRectGetMaxY(self.pictureImageView.frame) + 10;
    } else {
        return CGRectGetMaxY(self.text_label.frame) + 10;
    }
}

第十节

1.iOS面试相关

2. 数据刷新

3.全局刷新方法(最常用)

[self.tableView reloadData];
// 屏幕上的所有可视的cell都会刷新一遍

4.局部刷新方法

NSArray *indexPaths = @[
                        [NSIndexPath indexPathForRow:0 inSection:0],
                        [NSIndexPath indexPathForRow:1 inSection:0]
                        ];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight];
NSArray *indexPaths = @[
                        [NSIndexPath indexPathForRow:0 inSection:0],
                        [NSIndexPath indexPathForRow:1 inSection:0]
                        ];
[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationMiddle];
NSArray *indexPaths = @[
                        [NSIndexPath indexPathForRow:0 inSection:0],
                        [NSIndexPath indexPathForRow:1 inSection:0]
                        ];
[self.tableView relaodRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationMiddle];

5.左滑出现删除按钮

/**
 *  只要实现了这个方法,左滑出现Delete按钮的功能就有了
 *  点击了“左滑出现的Delete按钮”会调用这个方法
 */
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 删除模型
    [self.wineArray removeObjectAtIndex:indexPath.row];

    // 刷新
    [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}

/**
 *  修改Delete按钮文字为“删除”
 */
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return @"删除";
}

6.左滑出现N个按钮

/**
 *  只要实现了这个方法,左滑出现按钮的功能就有了
 (一旦左滑出现了N个按钮,tableView就进入了编辑模式, tableView.editing = YES)
 */
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{

}

/**
 *  左滑cell时出现什么按钮
 */
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewRowAction *action0 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"关注" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
        NSLog(@"点击了关注");

        // 收回左滑出现的按钮(退出编辑模式)
        tableView.editing = NO;
    }];

    UITableViewRowAction *action1 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
        [self.wineArray removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }];

    return @[action1, action0];
}

7.进入编辑模式

// self.tabelView.editing = YES;
[self.tableView setEditing:YES animated:YES];
// 默认情况下,进入编辑模式时,左边会出现一排红色的“减号”按钮

8.在编辑模式中多选

// 编辑模式的时候可以多选
self.tableView.allowsMultipleSelectionDuringEditing = YES;
// 进入编辑模式
[self.tableView setEditing:YES animated:YES];

// 获得选中的所有行
self.tableView.indexPathsForSelectedRows;

第十一节

代理的使用步骤

@property (nonatomic, weak) id<XMGWineCellDelegate> delegate;
if ([self.delegate respondsToSelector:@selector(wineCellDidClickPlusButton:)]) {
    [self.delegate wineCellDidClickPlusButton:self];
}

iOS监听某些事件的方法

上一篇下一篇

猜你喜欢

热点阅读