UI基础

框架介绍

  • QuartzCore:核心动画框架,用来做游戏的
  • Mapkit:地图框架,打车软件常用
  • CoreLocation:核心定位,QQ说说,外卖软件

代码仓库

存储不同版本应用程序代码,用于对比修改了那些地方,当新的代码出现问题,可以回退到上一个版本。包含svn/git两种

方法、属性与对象关系

  • 一个按钮可以连接多个方法,一个对象连接多个属性是没有必要的,只需要连接一个属性即可
  • 判断一个对象是否能够连线方法,需要看该对象的类是否继承于UIControl或者右键该对象看他是否包含sent events单词
  • NSSelectorFromString(NSString * _Nonnull aSelectorName):用于将字符串转化成方法
  • 只要方法名带有file的,都是传全路径
  • 如何抽方法
  • 先把相同的代码抽到方法中,不要设置方法名和参数
  • 把要变化的东西换成变量,然后编译,把报错的设置为方法的参数
  • 接口方法


    Snip20170122_48.png

控件

  • 孙子控件不是子控件,也就是说子控件的子控件不是我的子控件
  • 只要控件有父控件,就一定能够从父控件中移除
  • 控制器的view默认包含屏幕上下20像素高度的子控件,可以通过取消勾选去除子控件,如下图


    Snip20160103_41.png
"<_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执行伪代码如下图:


    Snip20160103_46.png

位置和尺寸

  • bounds:通过bounds改变尺寸,在iOS9以后,中心点不变向四周延伸
  • 结构体是值传递,不是地址传递

UIViewController的使用

  • 作用:负责处理软件界面的各种事件,并负责软件界面的创建和销毁
  • 注意:每一个控制器都会专门管理一个软件界面
  • 每一个控制器(UIViewController)内部都有个默认的UIView属性

UIImageView

Snip20170119_59.png
Snip20170119_58.png
Snip20170119_56.png
  • 判断图片控件是否在执行动画


    Snip20170119_67.png
  • 通过ARGB设置图片的背景色


    Snip20170119_71.png
  • 沙盒路径


    Snip20170119_61.png
  • 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),将其分别转换成模型数据,以数组方式存储,最后遍历显示到相应控件上去。
* 重复代码需要抽方法
* 可以考虑将经常变的数据放在文件中进行存储,程序启动后从文件中读取最新的数据。如果要变动数据,直接修改数据文件即可,不用修改代码
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350

推荐阅读更多精彩内容