viewWithTag
UIView *view = [self.view viewWithTag:100];
//内部原理
1.首先会跟自己匹配
2.如果自己不匹配,会遍历所有的子控件;首先会遍历subViews数组中第0个控件,如果不匹配,会遍历这个控件的子控件,依次遍历
3.如果都不匹配,会返回nil
界面初始化方法
- 用Storyboard创建的界面,所以初始化应该用 -(instancetype)initWithCoder:(NSCoder *)aDecoder 方法。
- 用的是代码或者xib创建的界面,则应该使用 -(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 初始化方法;
- -(void)awakeFromXib XIB加载完成时候调用
frame、bounds、center 区别
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
// 修改位置和尺寸,以父控件左上角为坐标原点
redView.frame = CGRectMake(100, 100, 200, 100);
// 修改尺寸,以自己左上角为坐标原点
// redView.bounds = CGRectMake(0, 0, 300, 200);
// 修改位置,以父控件左上角为坐标原点
// redView.center = CGPointMake(200, 200);
[self.view addSubview:redView];
UIImageView
- UIImageView的初始化
//第一种方式
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"2"]];
// initWithImage:会根据传入的图片创建imageView,并且imageView的尺寸等于图片的尺寸
[self.view addSubview:imageView];
//第二种方式
UIImageView *imageView = [[UIImageView alloc] init];
imageView.image = [UIImage imageNamed:@"2"];
imageView.frame = CGRectMake(0, 0, imageView.image.size.width, imageView.image.size.height);
[self.view addSubview:imageView];
// oc语法规定:不能直接修改oc对象结构体属性的成员
CGRect tempFrame = imageView.frame;
tempFrame.size = imageView.image.size;
imageView.frame = tempFrame;
- UIImageview 的内容模式
//带有scale:图片有可能会被拉伸
UIViewContentModeScaleToFill,
UIViewContentModeScaleAspectFit,
UIViewContentModeScaleAspectFill,
// 不带有Scale:显示出来的图片不会被拉伸,保持图片原来的宽高比例
UIViewContentModeCenter,
UIViewContentModeTop,
UIViewContentModeBottom,
UIViewContentModeLeft,
UIViewContentModeRight,
UIViewContentModeTopLeft,
UIViewContentModeTopRight,
UIViewContentModeBottomLeft,
UIViewContentModeBottomRight,
*/
- UIImageview 的缓存
- UITableviewCell 分割线内边距
方法1
// ios8 出现布局边缘
self.tableview.separatorInset = UIEdgeInsetsZero;
cell.layoutMargins = UIEdgeInsetsZero;
方法2
/*
1.取消tableview的分割线
2.设置tableview的背景色为分割线的颜色
3.setFrame 设置frame之前 ,把高度减 10
4.补回分割线的高度
*/
-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{
return 60 + 10;
}
- (void)setFrame:(CGRect)frame {
frame.size.height -= 10;
frame.origin.y +=10;
frame.origin.x += 10;
frame.size.width -= 20;
[super setFrame:frame];
}



contentSize、contentOffset、contentInset
contentSize:内容 滚动范围
内容无限大 ,可视区域
contentOffset: 偏移量 ,tableview顶点与内容顶点的距离
额外的滚动区域,超出内容可以滚动多少,额外滚动区域不属于内容
tableview默认会滚动到最上面
contentInset: 内边距
UI复习 基础
什么是控制器?
任何继承于UIViewController的类, 都称之为控制器
控制器的作用?
管理UI界面(负责管理UI界面的创建和一些事件的处理)
连线问题
- 一个控件可以关联多个属性,一个属性不可以关联多个控件
- 如果将属性和控件连线之后又将属性删除了, 那么只要程序运行就会报一个经典错误
[<ViewController 0x7fe9d9f1a5d0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key lable. - 任何UI控件都可以和属性进行连线, 但是并不是任何控件都可以和方法连线. 只有继承于UIControl的控件才可以连线
- 一个方法可以很多个控件关联,一个控件可以和很多方法进行连线
- 如果将按钮关联的方法删除, 运行之后会报一个经典错误
reason: '-[ViewController redBtnClick]: unrecognized selector sent to instance 0x7fb4aa618e50'
父子控件
虽然在Storyboard中不能将某个控件添加到另一个控件中, 但是只要通过代码, 所以继承于UIView的控件都可以添加子控件
通过Tag获取控件
viewWithTag只能查找当前控件和当前控件的子控件, 不能查找兄弟控件, 或者父控件
UISwitch *sw = [[UISwitch alloc] init];sw.tag = 998;
`UIView *sw = [self.view viewWithTag:998];
类扩展
匿名分类和分类的区别?
1.匿名分类没有名字, 分类有名称
2.匿名分类不需要有对应的实现, 而分类需要有对应的实现
3.匿名分类可以声明属性, 也可以声明方法, 分类只能声明方法
4.分类中的@property只会生成getter/setter方法的声明, 不会生成实现以及私有的成员变量
分类和原来注意点
1.如果多个分类中都有和原有类中同名的方法, 那么调用该方法的时候执行谁由编译器决定,会执行最后一个参与编译的分类中的方法
2.如果分类中有和原有类同名的方法, 会调用分类中的方法,也就是说会忽略原有类的方法
load 和 initialize
1.只要程序启动就会将所有类的代码加载到内存中, 放到代码区
2.load方法会在当前类被加载到内存的时候调用, 有且仅会调用一次
3.如果存在继承关系, 会先调用父类的load方法, 再调用子类的load方法
1.当前类第一次被使用的时候就会调用(创建类对象的时候)
2.initialize方法在整个程序的运行过程中只会被调用一次, 无论你使用多少次这个类都只会调用一次
3.initialize用于对某一个类进行一次性的初始化
4.initialize和load一样, 如果存在继承关系, 会先调用父类的initialize再调用子类的initialize
获取按钮状态的属性值
获得按钮的文字
- (NSString *)titleForState:(UIControlState)state
获得按钮的文字颜色
- (UIColor *)titleColorForState:(UIControlState)state
获得按钮内部的小图片
- (UIImage *)imageForState:(UIControlState)state
获得按钮的背景图片
- (UIImage *)backgroundImageForState:(UIControlState)state
解析Plist文件
获得Plist文件的全路径
NSBundle *bundle = [NSBundle mainBundle]; NSString *path = [bundle pathForResource:@"shops" ofType:@"plist"];
加载plist文件
_shops = [NSArray arrayWithContentsOfFile:path]
模型取代字典的好处
1.一般情况下,设置数据和取出数据都使用“字符串类型的key”,编写这些key时,编辑器没有智能提示,手敲字符串key,key容易写错,Key如果写错了,编译器不会有任何警告和报错,造成设错数据或者取错数据
2.所谓模型,其实就是数据模型,专门用来存放数据的对象,用它来表示数据会更加专业,模型设置数据和取出数据都是通过它的属性,属性名如果写错了,编译器会马上报错,使用模型访问属性时,编译器会提供一系列的提示,提高编码效率
instancetype 和 id
1.instancetype在类型表示上,跟id一样,可以表示任何对象类型
2.instancetype只能用在返回值类型上,不能像id一样用在参数类型上
3.instancetype比id多一个好处:编译时编译器会检测 instancetype的真实类型
封装控件的基本步骤
- 在initWithFrame:方法中添加子控件,提供便利构造方法
- 在layoutSubviews方法中设置子控件的frame(一定要调用super的layoutSubviews)
- 增加模型属性,在模型属性set方法中设置数据到子控件上
Xib和storyboard对比
共同点
- 都用来描述软件界面
- 都用Interface Builder工具来编辑
- 本质都是转换成代码去创建控件
不同点 - Xib是轻量级的,用来描述局部的UI界面
- Storyboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系
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];
注意点
一个控件有2种创建方式:
通过代码创建
初始化时一定会调用initWithFrame:方法
通过xib\storyboard创建
初始化时不会调用initWithFrame:方法,只会调用initWithCoder:方法
初始化完毕后会调用awakeFromNib方法
剪切超出UIImageView的部分
UIImageView *iv = [[UIImageView alloc]] init];
iv.clipsToBounds = YES;
播放动画
self.UIImageView.animationImages = arrM(存放图片); [[self. UIImageView startAnimating ]]; // 开始动画
资源拷贝注意事项
拷贝资源的时候选择的copy的含义:
是否要将资源拷贝一份到项目中, 如果不勾选就代表着不拷贝, 那么原来的资源不见了, 项目中的也不能用了
注意:
1.虽然项目中的图片和外部的图片是同一张图片, 但是这仅仅是在开发阶段, 如果将应用程序安装到手机上, 那么系统会自动给我们拷贝一张图片到手机中
2.虽然安装的时候会自动拷贝, 但是还是不建议大家不勾选copy。
图片除了可以放到supporting files中, 还可以放到Assets.xcassets文件夹中
> 如果是放到supporting files中, 使用图片的时候需要加上图片的后缀
> 如果是放到Assets.xcassets中, 使用图片的时候不需要加上图片的后缀
> 如果是放到Assets.xcassets中, 那么系统会自动对图片进行copy操作
> 如果是放到Assets.xcassets中, 可以对图片进行一些额外的属性设置
> 如果是放到Assets.xcassets中, 可以提高软件的安全性, 它会将图片都加密压缩保存到Assets.car文件中
** add to target的含义**
是否需要将资源打包到main bundle中(03-拷贝资源的选项.app)
> 如果不勾选就不会打包进去, 也就是说程序安装之后资源不会在手机上
**模拟器的路径:**
/Users/xiaomage/Library/Developer/CoreSimulator/Devices/
imageNamed: 默认是去mian bundle中加载, 如果是在mian bundle子文件夹中, 需要告诉系统具体的路径
播放本地音乐
NSURL *url = [[NSBundle mainBundle]] URLForResource:@"kyo_dazhao" withExtension:@".mp3"];
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[[self.player play]];`
layoutSubviews方法什么时候调用
1.只要一个控件尺寸确定, 那么就会调用
2.只要修改控件的尺寸就会调用(bounds/frame)
3.修改位置不会调用
4.如果当前修改的尺寸和上一次的尺寸没有变化, 不会调用