框架介绍
- QuartzCore:核心动画框架,用来做游戏的
- Mapkit:地图框架,打车软件常用
- CoreLocation:核心定位,QQ说说,外卖软件
代码仓库
存储不同版本应用程序代码,用于对比修改了那些地方,当新的代码出现问题,可以回退到上一个版本。包含svn/git两种
方法、属性与对象关系
- 一个按钮可以连接多个方法,一个对象连接多个属性是没有必要的,只需要连接一个属性即可
- 判断一个对象是否能够连线方法,需要看该对象的类是否继承于UIControl或者右键该对象看他是否包含sent events单词
- NSSelectorFromString(NSString * _Nonnull aSelectorName):用于将字符串转化成方法
- 只要方法名带有file的,都是传全路径
- 如何抽方法
- 先把相同的代码抽到方法中,不要设置方法名和参数
- 把要变化的东西换成变量,然后编译,把报错的设置为方法的参数
-
接口方法
控件
- 孙子控件不是子控件,也就是说子控件的子控件不是我的子控件
- 只要控件有父控件,就一定能够从父控件中移除
-
控制器的view默认包含屏幕上下20像素高度的子控件,可以通过取消勾选去除子控件,如下图
"<_UILayoutGuide: 0x7fd0d4603820; frame = (0 0; 0 0); hidden = YES; layer = <CALayer: 0x60800003c040>>":
- 每个控件都是个容器,能容纳其他控件
Tag
- tag:控件的ID,父控件可以通过tag来找到对应子控件
- 根据一个tag标识找出对应的控件(一般指子控件)
-(UIView *)viewWithTag:(NSInteger)tag;
- 尽量少使用tag,原因如下:
- tag的效率非常差
- tag使用多了容易乱
-
tag执行伪代码如下图:
位置和尺寸
- bounds:通过bounds改变尺寸,在iOS9以后,中心点不变向四周延伸
- 结构体是值传递,不是地址传递
UIViewController的使用
- 作用:负责处理软件界面的各种事件,并负责软件界面的创建和销毁
- 注意:每一个控制器都会专门管理一个软件界面
- 每一个控制器(UIViewController)内部都有个默认的UIView属性
UIImageView
-
判断图片控件是否在执行动画
-
通过ARGB设置图片的背景色
-
沙盒路径
- animationRepeatCount:动画的播放次数(默认是0,代表无限播放
- 其实UIImageView、UILabel也可以通过手势识别器来监听
UIButton
- highlighted(高亮状态)
- 按钮被按下去的时候(手指还未松开)
- 为了保证高亮状态下的图片正常显示,必须设置按钮的type为custom
- UIButtonTypeCustom:无类型,按钮的内容需要自定义
- 设置按钮的文字字体(需要拿到按钮内部的label来设置)
btn.titleLabel.font =[UIFont systemFontOfSize:13];
- 获得按钮的文字
-(NSString *)titleForState:(UIControlState)state;
- 获得按钮的文字颜色
- (UIColor *)titleColorForState:(UIControlState)state;
- 获得按钮内部的小图片
- (UIImage *)imageForState:(UIControlState)state;
- 获得按钮的背景图片
- (UIImage *)backgroundImageForState:(UIControlState)state;
* 直接通过addTarget...方法监听点击
![Snip20170121_21.png](http://upload-images.jianshu.io/upload_images/1609505-ce999b319c1622ef.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 创建UIButton
![Snip20170121_18.png](http://upload-images.jianshu.io/upload_images/1609505-1293f5b01cf3773f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 设置按钮字体偏移量
![Snip20170121_19.png](http://upload-images.jianshu.io/upload_images/1609505-d7209fdaad2cfbd6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#九宫格
![Snip20170121_29.png](http://upload-images.jianshu.io/upload_images/1609505-0c3de0d9110949de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Snip20170121_22.png](http://upload-images.jianshu.io/upload_images/1609505-4f12459c998c4405.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Snip20170121_23.png](http://upload-images.jianshu.io/upload_images/1609505-3d4cf47e1fc6e09a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#UILabel
* numberOfLines:文字行数
* lineBreakMode:换行模式
* 要想让UILabel自动换行,设置Lines为0即可
#模型
* 所谓模型,其实就是数据模型,专门用来存放数据的对象
#手机尺寸
![尺寸.jpeg](http://upload-images.jianshu.io/upload_images/1609505-10c69a4fc36feb62.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#view的封装
* 如果一个view内部的子控件比较多,一般会考虑自定义一个view,把它内部子控件的创建屏蔽起来,不让外界关心
* 外界可以传入对应的模型数据给view,view拿到模型数据后给内部的子控件设置对应的数据
* 代码-自定义封装控件的基本步骤:
* 在initWithFrame:方法中添加子控件,初始化子控件,提供便利构造方法
* 在layoutSubviews方法中设置子控件的frame(一定要调用super的layoutSubviews)
* 给子控件设置数据,对外增加模型对象属性,在模型属性set方法中设置数据到子控件上
* xIb自定义封装控件的基本步骤:
* 新建自定义控件类
![Snip20170120_6.png](http://upload-images.jianshu.io/upload_images/1609505-18f476c7aaf84fc8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 新建xib文件(文件名建议和view的类名一致)
![Snip20170120_1.png](http://upload-images.jianshu.io/upload_images/1609505-e0553de9e76eb509.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![0001.jpg](http://upload-images.jianshu.io/upload_images/1609505-254bc3a5f19b6b04.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 修改xib中view的类名
![Snip20170120_2.png](http://upload-images.jianshu.io/upload_images/1609505-40a82d63b337faa8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 封装xib的加载过程
![Snip20170120_3.png](http://upload-images.jianshu.io/upload_images/1609505-27cbf2b37c9cf45f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Snip20170120_4.png](http://upload-images.jianshu.io/upload_images/1609505-385e141a3ee1aad7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 增加模型属性,在模型属性set方法中设置数据到子控件上
* Xib是轻量级的,用来描述局部的UI界面
* 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];
* Storyboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系
* 一个控件有2种创建方式
* 通过代码创建
* 初始化时一定会调用initWithFrame:方法
* 通过xib\storyboard创建
* 初始化时不会调用initWithFrame:方法,只会调用initWithCoder:方法
* 初始化完毕后会调用awakeFromNib方法
* 有时候希望在控件初始化时做一些初始化操作,比如添加子控件、设置基本属性
* 这时需要根据控件的创建方式,来选择在initWithFrame:、initWithCoder:、awakeFromNib的哪个方法中操作
#颜色认知
![Snip20170121_7.png](http://upload-images.jianshu.io/upload_images/1609505-1b471c932e2dbfdd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Snip20170121_8.png](http://upload-images.jianshu.io/upload_images/1609505-2214608c98e22a6e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Snip20170121_9.png](http://upload-images.jianshu.io/upload_images/1609505-5527a3bbd74df85e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Snip20170121_10.png](http://upload-images.jianshu.io/upload_images/1609505-13a9c76165598f4e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Snip20170121_11.png](http://upload-images.jianshu.io/upload_images/1609505-a4d22ad05169fadb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Snip20170121_13.png](http://upload-images.jianshu.io/upload_images/1609505-d598dc2b2dc1d91d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Snip20170121_14.png](http://upload-images.jianshu.io/upload_images/1609505-6c8597bbb0c294bb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Snip20170121_16.png](http://upload-images.jianshu.io/upload_images/1609505-1b8d26a8374449bd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#Autolayout
* 屏幕
* 屏幕是由无数个点组成的,点又是由像素组成的
* 非retina屏幕:1个点由1个像素组成
* 0retina屏幕:1个点由4个像素组成
* Autolayout的警告和错误
* 警告
* 控件的frame不匹配所添加的约束
* 比如约束控件的宽度为100, 而控件现在的宽度是110
* 错误
- 缺乏必要的约束
* 比如只约束了宽度和高度, 没有约束具体的位置
* 两个约束冲突
* 比如1个约束控件的宽度为100, 1个约束控件的宽度为110
* 代码实现Autolayout的注意点
* 要先禁止autoresizing功能,设置view的下面属性为NO
view.translatesAutoresizingMaskIntoConstraints = NO;
* 不用再给view设置frame
* 创建约束对象的常用方法
* view1 :要约束的控件
* attr1 :约束的类型(做怎样的约束)
* relation :与参照控件之间的关系
* view2 :参照的控件
* attr2 :约束的类型(做怎样的约束)
* multiplier :乘数
* c :常量
+(id)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
* 添加约束的规则
* 对于两个同层级view之间的约束关系,添加到它们的父view上
![12.png](http://upload-images.jianshu.io/upload_images/1609505-13e7e8547ea796cd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 对于两个不同层级view之间的约束关系,添加到他们最近的共同父view上
![23.png](http://upload-images.jianshu.io/upload_images/1609505-8d65c0ec02bc8924.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 对于有层次关系的两个view之间的约束关系,添加到层次较高的父view上
![3333.png](http://upload-images.jianshu.io/upload_images/1609505-a378eaacd52820d1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* VFL示例
- canelButton宽72,acceptButton宽50,它们之间间距12
- H:[cancelButton(72)]-12-[acceptButton(50)]
- wideView宽度大于等于60point,该约束条件优先级为700(优先级最大值为1000,优先级越高的约束越先被满足)
- H:[wideView(>=60@700)]
- 竖直方向上,先有一个redBox,其下方紧接一个高度等于redBox高度的yellowBox
- V:[redBox][yellowBox(==redBox)]
- 水平方向上,Find距离父view左边缘默认间隔宽度,之后是FindNext距离Find间隔默认宽度;再之后是宽度不小于20的FindField,它和FindNext以及父view右边缘的间距都是默认宽度。(竖线“|” 表示superview的边缘)
- H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|
* 使用VFL来创建约束数组
* format :VFL语句
* opts :约束类型
* metrics :VFL语句中用到的具体数值
* views :VFL语句中用到的控件
* 创建一个字典(内部包含VFL语句中用到的控件)的快捷宏定义
- (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;
NSDictionaryOfVariableBindings(...)
* 基于Autolayout的动画
- 在修改了约束之后,只要执行下面代码,就能做动画效果
[UIView animateWithDuration:1.0 animations:^{
[添加了约束的view的父控件 layoutIfNeeded];
}];
* Masonry
- mas\_equalTo和equalTo
* 默认情况下
* mas\_equalTo有自动包装功能,比如自动将20包装为@20
* equalTo没有自动包装功能
* 如果添加了下面的宏,那么mas\_equalTo和equalTo就没有区别
#define MAS_SHORTHAND_GLOBALS
// 注意:这个宏一定要添加到#import "Masonry.h"前面
- mas\_width和width
* 默认情况下
* width是make对象的一个属性,用来添加宽度约束用的,表示对宽度进行约束
- mas\_width是一个属性值,用来当做equalTo的参数,表示某个控件的宽度属性
* 如果添加了下面的宏,mas\_width也可以写成width
define MAS_SHORTHAND
* mas\_height、mas\_centerX以此类推
* 可有可无的用法
* 以下方法都仅仅是为了提高可读性,可有可无
-(MASConstraint *)with {
return self;
}
- (MASConstraint *)and {
return self;
}
* 约束的动画
* 先改变约束对象的值:
self.redViewW.constant = 50;
* 然后刷新整个视图
[UIView animateWithDuration:2.0 animations:^{
// 强制刷新
[self.view layoutIfNeeded];
}];
* UILabel实现包裹内容
* 设置宽度约束<= 固定值
* 设置位置约束
* 不需要设置高度约束
* 万能公式
obj1.property1 =(obj2.property2 * multiplier)+ constant value
#UIScrollView
![Snip20170126_76.png](http://upload-images.jianshu.io/upload_images/1609505-474e79dff8a45bc8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Snip20170126_78.png](http://upload-images.jianshu.io/upload_images/1609505-b07066abe4a08973.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Snip20170126_79.png](http://upload-images.jianshu.io/upload_images/1609505-2b3d68a17bc5b949.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Snip20170127_81.png](http://upload-images.jianshu.io/upload_images/1609505-4d3f78969d36162e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#控制器view的延迟加载
- 控制器的view是延迟加载的:用到时再加载
- 可以用isViewLoaded方法判断一个UIViewController的view是否已经被加载
- 控制器的view加载完毕就会调用viewDidLoad方法
#总结
* 先搭建界面,然后向服务器发送请求,获取网络数据,解析网络数据(xml/json),将其分别转换成模型数据,以数组方式存储,最后遍历显示到相应控件上去。
* 重复代码需要抽方法
* 可以考虑将经常变的数据放在文件中进行存储,程序启动后从文件中读取最新的数据。如果要变动数据,直接修改数据文件即可,不用修改代码