第一天笔记

上午笔记

使用IBOutlet修饰的属性统一使用weak修饰

因为UIWindow会强引用ViewController

@property(nullable,nonatomic,strong)UIViewController *rootViewController;

而ViewController又会强引用UIView容器

@property(null_resettable,nonatomic,strong)UIView *view;

而在往XIB或storyboard中的视图控制器中对应的UIView容器中拖入一个控件时UIView容器就会强引用该视图

当ViewController要销毁的时候,UIView也会被销毁,UIView的子视图也会随着销毁,如果属性插座连线时使用strong,那么引用计数器将多+1,造成无法销毁

@interface ViewController ()

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

@end


2.XIB或storyboard中一个按钮可以连接多个方法,执行顺序应该是按照连线的顺序从后往前执行,即最后连线的最先执行,栈方式,同时一个控件也可以连线多个属性,但这样做没有必要


3.self.view.superview只有在视图已经出现的时候才能拿到值UIWindow,在之前的声明周期中是拿不到的

(void)viewDidAppear:(BOOL)animated {

NSLog(@"%@", self.view.superview);

}

<UIWindow: 0x7f90fbd56a40;

frame = (0 0; 375 667);

autoresize = W+H;

gestureRecognizers = <NSArray: 0x7f90fbd57e60>;

layer = <UIWindowLayer: 0x7f90fbd53fb0>>

4.UIView中tag的作用

通过viewWithTag:方法获取对应的控件(该场景使用有缺点:tag的效率非常差,tag使用多了容易乱,应尽量少用)

使用tag用于条件判读,用于区分不同的控件

5.bounds:的坐标系是相对于当前控件而言的,即坐标系的原点和控件的左上角的坐标一致,该变bounds的宽度和高度的效果是:控件的中心点保持不变,宽度和高度向上下或左右同时缩放

6.UIImageView contentModel(内容模式)

Scale: 缩放(拉伸或压缩) 会显示整个图片的所有内容而不会只显示局部,只不过会高度或宽度会被拉伸或压缩

Aspect: 宽高比例不变

Fill:会将UIImageView填充满,一般填充会失真,将图片变的太胖或太瘦

Fit:适应

  • ScaleToFill :缩放填充(对原图进行缩放,不考虑比例)
  • ScaleAspectFit: 成比例缩放图片来适应UIImageView(一般不会充满整个UIImageView)
  • ScaleAspectFill:显示原图部分

原图:

ScaleToFill:缩放填充:根据UIImageView的宽高,如果超出了就收缩,不够就拉伸


ScaleAspectFit:成比例缩放,当高度或宽度有一方缩放到UIImageView的宽度或高度一致时就停止缩放


ScaleAspectFill:成比例缩放,一直成比例缩放,一直将宽度和高度同时 将到UIImageView的宽高一致时为止来填满整个UIImageView,此种情况有可能会导致图片显示不完整


毛玻璃:将UIToolbar控件添加到UIImageView上就会产生毛玻璃效果(朦胧美,看不清,只能模糊的看到轮廓),因为UIToolbar就是毛玻璃效果,将UIToolbar覆盖掉UIImageView就会使背后的图片产生朦胧美

(void)viewDidLoad {

UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.frame];

imageView.image = [UIImage imageNamed:@"angelababy.jpg"];

imageView.contentMode = UIViewContentModeScaleToFill;

[self.view addSubview:imageView];

// 毛玻璃:朦胧美

UIToolbar *toolbar = [[UIToolbar alloc] init];

toolbar.frame = imageView.bounds;

toolbar.barStyle = UIBarStyleDefault;

[imageView addSubview:toolbar];

}


沙盒

Documents

Library

tmp


UIImage两种初始化方式

[UIImage imageNamed:@”angelababy.jpg”];

NSString *path = [[NSBundle mainBundle] pathForResource:@”angelababy” ofType:@”jpg”];

[UIImage imageWithContentsOfFile:path];

imageNamed:

即可加载项目中的图片也可以加载Assets.xcassets中的图片

如果指向图片的指针被销毁,图片资源仍然会占用内存

图片经常使用的时候,使用该方式

imageWithContentOfFile:

只能加载项目中的图片,不能加载到Assets.xcassets中的图片

如果指向图片的指针被销毁,图片资源会立即释放掉该内存

放到项目中的图片就不带缓存

不经常用的,大批量的图片使用该种方式加载

方法的参数第一个参数一般使用With介词

IPA是Apple程序应用文件iPhoneApplication的缩写。简单来说,Mac下的软件就像是 Windows 下的绿色软件一样,解压后即可使用,不需要安装,卸载的话也只用删除程序文件即可

播放器AVPlayer

#import <AVFoundation/AVFoundation>

NSString *path = [[NSBundle mainBundle] pathForResource:@"xxx.mp3" ofType:nil];

NSURL *url = [NSURL fileURLWithPath:path];

NSURL *url = [[NSBundle mainBundle] URLForResource:@"xxx.mp3" withExtension:nil];

// 播放项

AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithUL:url];

// 播放器

AVPlayer *player =[[AVPlayer alloc] initWithPlayerItem:playerItem];

player.rate = 2.0; // 播放速率

[player play];

[player pause];

// 替换当前项使用播放项

[player replaceCurrentItemWithPlayerItem:playerItem];

免费图标网站,有大量app可用的图标

UIButton

4中类型Type:不同类型的属性值不一样

Custom : 自定义

System : 系统

Detail Disclosure :详细图标i

Add Contact :添加图标+

五种状态State,在不同的状态下设置不同的属性

normal(default) : 正常

highlighted :高亮

disabled :禁用

selected :选中

focused :聚焦

当UIButton的image和title同时有值时效果为图标在左边,文字在右边的情况,在storyboard中IButton的size会随着image的尺寸变化,如果图标比UIButton的size要大,那么UIButton的size将会变大,在纯代码中不会,如果UIButton只有image或title一个有值会居中显示


edge:内边距
Content
Title
Image
UIButton由UIImageView +UILabel组成
九宫格坐标计算公式
已知变量:宽度、高度、行数、列数
int index = 0;
索引 = 子视图总个数
列间距数 = 总列数 - 1;
行间距数 = 总行数 - 1;
行数 = 下标 % 总列数
列数 = 下标 / 总行数
x = column * (width + rightMargin)
y = row * (height + bottomMargin)
column = value % totalColumns =
row = (int)value / totalRows =
NSInteger columns = 3; //总列数
NSInteger rows = 3; //总函数
CGFloat width = 80;
CGFloat height = 100;
CGFloat columnMargin = (UIView的宽度 - 总的单元格的宽度)/ 垂直间距数 = (self.view.frame.size.width - columns * width) / (columns - 1); //垂直间距
CGFloat rowMargin = (UIView的高度 - 总的单元格的高度) / (总行数 - 1)=
(self.view.frame.size.height - rows * height)/ (rows - 1)
x = (width + columnMargin) * (index % totalColumns)
y = (height + rowMargin) * (index / totalRows)
self.view.frame = CGRectMake(x, y, width, height);
index++
下午笔记

self.name = @”xxx”; _name = @”xxx”;第一种方式走settro方法,第二种方式直接赋值不走settor方法;

[[MyView alloc] init] 会先调用 initWithFrame:CGRectZero 然后再调用init方法

纯代码自定义控件的步骤:

1.重写initWithFrame:方法 用来初始化子控件

2.重写layoutSubviews方法 用来设置坐标进行布局

3.提供设置数据源model的方法 setXXx用于给子控件填充内容

4.也可以提供便利的构造方法进行数据源的初始化来优化

Xib自定义控件

1.重写initWithCoder:方法 做一些额外的初始化操作,控件一般由Xib画

2.重写layoutSubviews方法 用来设置坐标进行布局

3.提供设置数据源model的方法 setXXx用于给子控件填充内容

注意:在使用xib或storyboard,或者自定义控件时,一般子控件都是使用weak来修饰,因为子控件最终会别添加到父控件中,引用计数最终会被+1, 所以不需要额外

使用XIB时,初始化不会调用init和initWithFrame:方法的,调用initWithCoder方法,而在这个方法中,所有的子控件还都没有唤醒,没有唤醒是无法获取不到控件的,也不能对子控件进行操作,当initWithCoder执行完成后会调用awakeFromNib来唤醒所有的子控件,在这个方法中是可以对子控件进行操作的。另外加载XIB文件使用 loadNibNiamed:owner:options 方法来加载

// UIView动画:值随着时间的流逝在不断改变)

对x/y(平移)

width/height(缩放、

alpha(透明度)

[UIView animateWithDuration:animations:];

调整UIButton中的图片和标题的位置:

默认情况下调整UIButton中的图片和标题的坐标没有效果,需要继承UIButton 并重写layoutSubviews 在布局子视图方法中修改imageView和titleLabel中的frame

或者重写imageRectWithContentRect: 和 titleRectWithContentRect:方法也可以

UIButton内边距

通过调整内边距edge,可以随意调整UIButton中imageView和titleLabel中的位置,例如:图片在右边,标题在左边;图片在上边,标题在下边; edge包括content/image/title,content是包含image和title的一个整体,在XIB上可以直观的调整


图片拉伸:

图片拉伸一般是将除了图片的中心点宽1像素,高1像素这样1X1这样的面积以外作为保护区域,将这个1X1这个面积进行平铺或拉伸形成新的图片

受保护的区域:

图片的上半部分,

图片的左半部分,

方式1:显式指定4个受保护的区域

可调整大小的图片使用保护区域

(UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets;
(UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode
UIImage *resizableImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(imageHeight * 0.5, imageWidth * 0.5, imageHeight * 0.5 -1, imageWidth * 0.5 -1)];UIImageResizingMode:
UIImageResizingModeTile, 平铺(默认)
UIImageResizingModeStretch 拉伸

方式2:显式指定2个受保护的区域,其他两个区域由系统根据固定的公式进行计算

拉伸图片使用左保护区

//右边需要保护的区域 = 图片的宽度 - leftCapWidth -1 = 1
//底部需要保护的区域 = 图片的高度- topCapHeight - 1 = 1
UIImage resizableImage = [image stretchableImageWithLeftCapWidth:imageWidth  0.5 topCapHeight:imageHeight * 0.5];

KVC作用:

KVC能够自动类型转换

KVC可以操作私有成员变量,用于修改系统的成员变量,例如将UIPageControl中的原点换成自定义图片

用于简单的字典转模型, 模型转字典

获取数组中所有模型的某个字段值

KVO:NSObject已经使用类别为NSObject添加了一些方法,所以直接实现即

可用于监听UIScrollView的滚动操作

监听tabBar的切换

// 1.添加观察者
addObserver:forKeyPath:options:context
// 2. 观察值对于键路径
observeValueForKeyPath:ofObject:change:context
// 3. 移除观察者
removeObserver:forKeyPath

UIScrollView

CGSize contentSize: 内容尺寸:即滚动范围CGSize

CGPoint contentOffset:内容偏移量

UIEdgeInsets contentInsets:内边距

BOOL scrollEnable:滚动能力,默认YES(不能滚动,但是允许其他交互方式,比较温柔)

BOOL userInteractionEnable: UIView中的属性,是否允许用户交互, 默认YES(自己和所有子控件都不允许操作, 比较暴力)

BOOL bounces:弹簧效果,默认YES

BOOL alwaysBounceHorizontal:总是弹簧水平方向

BOOL alwaysBounceVertical:总是弹簧垂直风向

BOOL showsHorizontalScrollIndicator:显示水平方向滚动指示器

BOOL showsVerticalScroolIndicator:显示垂直方向滚动指示器

UIScrollView要想能够滚动需要设置滚动范围contentSize并且范围要大于frame的尺寸,等于或小于都不行,

滚动的不是UIScrollView而是滚动的内容

UIScrollView滚动到contentSize的边界还是可以再滚动一点,其实这是弹簧效果,放手后会自动弹回来,增加体验下验性


alwaysBounceHorizontal和alwaysBounceVertical不管有没有设置contentSize都会有弹簧效果,可用于实现上拉加载更多,加载更多,下拉刷新效果

从父视图中拿所有的子控件并不是所有情况下拿到的子控件的个数大于显式添加到父视图的个数,例如

UIScroollView中的subviews:子控件不光是你自己显式添加上去的,水平滚动条是一个UIImageView,垂直方向的滚动条也是一个UIImageView,滚动条的长短是根据contentSize来计算的,所以如果UIScroolView中显示添加了一个子控件,那么子控件总是是3个,而且因为有两个滚动条,在获取subviews的时候得到的结果数组的顺序是不固定的,所以不要试图索引来获取你自己添加的子视图,可以通过循环判断找到子视图,如果要通过索引获取,将水平和垂直方向的滚动条隐藏

掉才可以

contentOffset:内容偏移量,将内容在横坐标和竖坐标进行移动,用于控制局部内容出现在视野中

UIScrollView左上角的坐标 - 内容左上角的坐标

UIScrollView(x, y)- content(x, y) = contentOffset

左上的偏移量为正值,右下的偏移量为负值



UIImageView是用来盛放图片的容器,当图片内容大于容器的时候多余的部分会漏出来,就像兜里的钱太多会暴漏在外边一样,我们可以通过UIView中的属性来自动剪裁边框clipsToBounds将多余的部分给剪裁掉,这样多余的部分就不会展示出来;UIScrollView默认是YES所以多余的内容不会展示

contentInsets:内边距top,left, bottom, right 默认情况下当UIScrollView的内容滚动到上下左右的边界再滚动会展示内容的边界,边界内容和UIScrollView的边界保持一致,如果设置内边距,当内容滚动到边界的时候还可以再滚动内边界值,并且不会被弹回去

应用:当使用contentOffset进行定位的时候,如果不小心碰到滚动内容,此时如果放手的会,内热会自动弹回去,如果需要用户主动慢慢的拖拽,需要使用contentInsets对内边界设置,留出一段空间来,让内容边界和UIScrollView边界保持一段距离


UIScrollView具有惯性,即当拖动过之后手放开,内容还会自动减速滚动一小会,将像生活中的惯性一样

代理方法包括:拖拽(即滚动)、减速、缩放

//将要开始拖拽、已经滚动、将要结束拖拽、已经结束拖拽

(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;

(void)scrollViewDidScroll:(UIScrollView *)scrollView;

(void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset;

(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView;

(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;

//将要开始减速、已经结束减速

(void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;

(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;

//将要开始缩放、已经缩放、已经结束缩放、缩放的子控件

(void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view ;

(void)scrollViewDidZoom:(UIScrollView *)scrollView;

(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale;

(nullable UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;

// 是否滚动到顶部

(BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView;

// 已经滚动到顶部

(void)scrollViewDidScrollToTop:(UIScrollView *)scrollView;
// 将要开始拖拽
[ViewController scrollViewWillBeginDragging:]
// 已经在滚动
[ViewController scrollViewDidScroll:]
// 将要结果拖拽
[ViewController scrollViewWillEndDragging:withVelocity:targetContentOffset:]
// 已经结束拖拽
[ViewController scrollViewDidEndDragging:willDecelerate:]
// 将要开始减速
[ViewController scrollViewWillBeginDecelerating:]
// 由于惯性还在滚动
[ViewController scrollViewDidScroll:]
// 已经结束减速
[ViewController scrollViewDidEndDecelerating:]

判断滚动是否结束严禁的做法应该是结合scrollViewDidEndDragging和scrollViewDidEndDecelerating 方法同时来判断,例如:当用户拖动了一会手没有放开,此时已经没有减速的机会,此时应该通过scrollViewDidEndDragging判断,如果用户滚动之后立即松开就会有减速的机会,此时通过scrollViewDidEndDecelerating判断更准确

任何遵守协议的OC对象都可以成为代理对象

苹果的代理为什么都是weak引用?防止循环引用

首先根视图控制器会强引用UIViewController,而UIViewController会强引用view,而UIView会强应用subviews,而数组中的子元素会强引用子空间,而子控件例如UIScrollView中有个delegate的值一般是当前视图控制器self, 如果delegate = self; 是强引用就会造成一个的死循环,当rootViewController不在引用UIViewController的时候造成UIView无法释放


只要是继承自UIControl的控件都可以通过addTarget:action:forControlEvents方式来监听事件

取消键盘

[self.view endEditing:YES]; //调用textField的父控件

[self.textField endEditing:YES];

[self.textField reginFirstResponder];

UIScrollView缩放图片

设置最小最大缩放比例minimumZoomScale、maximunZoonScale

实现代理方法返回要缩放的子控件viewForZoomingInScrollView:

对于定时器的属性声明使用weak即可,因为NSTimer已经由NSRunLoop管理了,所以声明时用weak即可

@implementation ViewController

#pragma mark -

#pragma mark - Touch Up Inside Event

(void)viewDidLoad {

// ImageAutoLooper 图片轮播器

// 一页就是UIScrollView的宽度,一般情况下会先创建好所有的ImageView,但如果用户没有滚动就造成浪费,特别是图片张数特别多的时候,一般情况下先创建3张

int count = 5;

int width = self.scrollView.frame.size.width;

int height = self.scrollView.frame.size.height;

for (int i = 0; i < count; i++) {

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(i * width, 0, width, height)];

imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"img_0%d", i + 1]];

[self.scrollView addSubview:imageView];

}

self.scrollView.showsVerticalScrollIndicator = NO;

self.scrollView.showsHorizontalScrollIndicator = NO;

self.scrollView.contentSize = CGSizeMake(width * count, 0);

self.scrollView.pagingEnabled = YES; // 不设置此值滚动图片滚动一半的时候是不会自动滚动上一页或下一页的

self.scrollView.delegate = self;

UIPageControl *pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(150, 450, 60, 30)];

pageControl.numberOfPages = count;

pageControl.pageIndicatorTintColor = [UIColor greenColor];

pageControl.currentPageIndicatorTintColor = [UIColor redColor];

pageControl.currentPage = 0;

[pageControl setValue:[UIImage imageNamed:@"current"] forKeyPath:@"_currentPageImage"];

[pageControl setValue:[UIImage imageNamed:@"other"] forKeyPath:@"_pageImage"];

self.pageControl = pageControl;

[self.view addSubview:pageControl];

if (count < 1) {

// self.pageControl.alpha = 0;

self.pageControl.hidden = YES;

}

self.pageControl.hidesForSinglePage = YES;// 单页是否隐藏

[self startTimer];

}

(void) nextPage {

long nextPage = self.pageControl.currentPage + 1;

if (nextPage == 5) {

nextPage = 0;

}

self.scrollView.contentOffset = CGPointMake(nextPage * self.scrollView.frame.size.width, 0);

}

// 当用户开始拖拽的时候,暂停定时器

(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {

[self stopTimer];

}

// 停止拖动的时候再启动定时器

(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {

[self startTimer];

}

(void)scrollViewDidScroll:(UIScrollView *)scrollView {

self.pageControl.currentPage = self.scrollView.contentOffset.x / self.scrollView.frame.size.width;

}

(void)startTimer {

self.timer = [NSTimer scheduledTimerWithTimeInterval:2.f target:self selector:@selector(nextPage) userInfo:nil repeats:YES];

}

(void)stopTimer {

[self.timer invalidate];

self.timer = nil;

}

@end

适配

系统适配(根据不同系统版本调用不同的方法)

屏幕适配

尺寸适配(iphone: 3.5/4.0/4.7/5.5 ipad:7.9/9.7/12.9)

横竖屏适配(一般是只支持竖屏)

在用户眼里屏幕是由像素组成的,像素越多,屏幕越清晰

在开发者眼中屏幕是由无数个点(坐标点)组成的,点又是像素的组成部分,在非retain屏幕中,一个像素=一个点, 在视网膜屏幕中 2X2=4个点=1个像素

屏幕适配历史

固定值—》autoresizingMask—》autolayout—-》sizeClasses

iphone1-iphone4s时代屏幕尺寸固定为(320, 480),我们只需要简单的计算相对位置即可

iphone5-iphone5s时代屏幕的尺寸变为(320,568),这时AutoresizingMask派上用场了(当时iOS6为最新系统,为了支持iOS5)

iphone6时代屏幕宽度也发生了变化,是时候抛弃AutoresizingMask了改用AutoLayout了(iOS8已出来不用再支持iOS5了,相对于屏幕适配的多样性AutoresizingMask也过时了)

1.屏幕尺寸不可能发生变化(320, 480)乔布斯说3.5寸是最适合人类的,所以屏幕的宽高固定写死或者定义成宏常量

方式1:直接写死值

button.frame = CGRectMake(320 - buttonWidth, 480 - buttonWidth, buttonWidth, buttonWidth);

方式2:宏常量固定值

define ScreenWidth 320

define ScreenHeight 480

方式3:宏常量代码

define ScreenWidth [UIScreen mainScreen].bounds.size.width

define ScreenHeight [UIScreen mainScreen].bounds.size.width

autoresizingMask(相对于autolayout有些不足)为了解决ipad上的问题

autoresizing : 自动调整尺寸, autoresizing和autolayout技术是互斥的,不能同时使用,要想使用autoresizing 必选关闭autolayout

sizeClassess技术必须依赖autolayout技术

autoresizing 如果设置线条矛盾,会有优先级, autoresizing是相对于父视图而言的 , width和height:会根据父视图的大小成比例缩放

UIViewAutoreszing autoresizingMask;

UIViewAutoreszingFlexibleLeftMargin 左边距灵活的,可伸缩的

UIViewAutoreszingFlexibleBottomMargin

UIViewAutoreszingFlexibleRightMargin

UIViewAutoreszingFlexibleTopMargin

UIViewAutoreszingFlexibleHeight

UIViewAutoreszingFlexibleWidth

xxxView.autoresizingMask = UIViewAutoreszingFlexibleLeftMargin |UIViewAutoreszingFlexibleTopMargin; 左边可以伸缩,顶部可以伸缩, 和xib好像正好相反

xib是说那些值是固定的, 代码是说那些方向是可以伸缩的,所以同一个效果两种方式设置的正好相反

可以通过Preview 预先查看在不同尺寸上的手机大概的样子,为了解决切换模拟器花费很长的时间来启动的优化

万能公式: obj1.property1 = (obj2.property2 * Multiplier) * Constant;

multiplier:倍数

constant:常量

可以通过拖线的方式,也可以通过右下角工具栏 都可以完成约束,只是提供了不同的操作习惯而已,完成约束,通常都有很多种做法来实现

约束包括:

对齐方式(上、下、左、右、水平居中、垂直居中对齐),

间距:顶部、底部、左、右 间距

等值:等高、等宽

常量值:

有些约束不好操作的话,可以先设置该约束,然后修改参数值即可

添加约束可以先搞定一个,让其他相对于这个进行设置,也可以同时对多个控件进行约束,

UILabel 默认会将顶部和底部空出来一部分,导致大片区域空白,当为UILabel只添加坐标而不添加宽高约束并不会报约束错误,是因为UILabel根据内容会自动计算宽度和高度,所以只需添加坐标约束,不许要添加尺寸约束,但有个问题当内容过多的时候,应该是在什么时候要换行呢,所以还需要给个宽度约束,Less Than or Equal 的意思是当内容宽度小于给定的值,宽度为内容的宽度,当内容大于这个最大宽度时,就自动换行,只要设置了宽度,AutoLayout会自动根据宽度和内容的长度来计算UILabel的高度, 同理UIButton的内部也是UILabel,所以UIButton只设置位置,不设置尺寸也可以,因为尺寸系统会根据内容自动计算

代码添加约束:代码方式太耗时,编码量大

NSLayoutConstraint constraintWithItem

对于添加约束,高度和宽度是相对于自己的约束,所以直接将约束添加到目标控件上即可,对于其他约束如间距应添加到最近的父视图上,不同种类的约束添加在不同的作用目标上

使用NSLayoutConstraint 添加约束时,先将控件的转换自动调整尺寸到约束禁止掉redView.translatesAutoresizingMaskIntoConstraints = NO;

VFL:可视化格式语言Visual Formate Language,为了简化 NSLayoutConstraint 代码量太大的问题,分为水平方向和垂直方向的约束

Priority: Required(1000) High(750) Low(250) :当出现类型相同的约束时通过优先级决定优先使用哪个约束,优先级高的约束是实线,低的约束是虚线,当优先级高的约束不存在的时候,低优先级就会起作用

约束也可以声明成IBOutlet,也可以进行拖拽,@property(weak, nonatomic) IBOutlet NSLayoutConstraint *view;在代码中直接修改NSLayoutConstraint的属性值即可,通过修改约束实现动画, 需要先修改约束,然后调用layoutIfNeeded方法作为动画代码

self.heightLayoutConstraint.constant = 310;
[UIView animateWithDuration:2.0 animations:^{
[self.view layoutIfNeeded\];   必须是父控件,子控件没有动画效果}];

mansory:在引入masonry.h文件前引入两个宏,

define MAS_SHORTTHAND // 属性mas_left 等都可去掉mas_前缀,

define MAS_SHORTTHAND_GLOBALS // 在调用方法如mas_equalTo可以省略掉前缀使代码更加简洁

代码添加约束时,控件必须先添加到父视图上,因为约束会基于父视图,不添加到父视图就不知道子控件的父视图是哪个

UITableView

UITableView属性:

style:样式 plain、grouped

tableHeaderView:表头视图,实际应用于图片轮播器,广告等

tableFooterView:表尾视图,实际应用于 “上拉加载更多” 等操作

separatorColor:分隔线颜色

UITableViewCell属性:

rowHeight:行高

backgroundView:背景视图

contentView:内容视图

selectionStyle:选中样式

selectedBackgroundView:选中背景视图

style:样式

sectionHeaderHeight:段头高度

sectionFooterHeight:段尾高度

sectionHeaderView:段头视图

sectionFooterView:段尾视图

accessoryType:配件类型

accessoryView: 配件视图
UITableView有很多代理方法,其中有些代理方法也是可以通过属性统一设置的,不过通过属性只能统一设置,而通过代理方法可以根据不同的行进行不同的设置

UITableViewCell子控件懒加载模式:

UITableViewCell有一个子控件contentView,contentView中有多个子控件:imageView,textLabel,accessoryStyle|accessoryView,detailTextLabel,当给cell的子控件赋值时可以看到,只有对子控件赋值时,该控件才会被添加到contentView中,这是懒加载思想

iOS 提供了一个UITableViewController,继承自UIViewController并实现了UITableView的协议和声明了tableView属性,便于开发者开发,需要注意的是 self.view = tableView; self.view 和tableView指向同一个对象tableView;

UITableView性能优化:

控件每展示一个cell就会调用一次cellForRowAtIndexPath,所以该方法会被频繁的调用,而该方法会返回一个cell,所以减少该方法的调用次数和优化cell的创建就极为重要,首先苹果为了减少调用次数,苹果只会调用 tableView.frame.size.height/tableView.rowHeight = UITableView在视野中能展示的个数N,这样当数据量比较大时不会出现一下子调用很多次,当用户向上滚动加载更多时,苹果再重新计算需要加载的单元格个数,当cell需要展示在视野的时候再加载,而不会一下子全部加载。当cell出现在视野中就会调用cellForRowAtIndexPath,无论cell是否已经加载过还是尚未加载过,都会调用该方法,所以当cell已经加载过了,还要调用cellForRowAtIndexPath,在这种情况下应该避免创建新的cell而使用之前创建过的cell,为了达到这种目的,苹果提供了一个叫”缓存池”的概念,“循环利用”,当用户加载新的cell,第一个消失在屏幕的cell将被放入缓存池,注意缓存池只存放上次消失的cell,对于刚开始加载表格的时候,cell是不会放入到缓存池中的,所以第一次刚加载出现在视野中的单元格都是新创建的,后面的都是从缓存池中获取的,重复利用的,所以对于cell统一的设置可以放在if(cell == nil)的判断里,因为缓存池中会存放多个tableView的cell,每个tableView对应一种cell,所以需要给cell起一个别名标示一下,因cellForRowAtIndexPath会频繁调用,所以标识符应声明为静态局部变量,这样该变量在整个应用程序中会一直存在,并且只会占用一个内存地址,苹果为了减少if(cell == nil)判断,提供了注册类的方法对于重用的单元格标识符 registerClass:forCellReuseIdentifier: ,注册之后,dequeueReusableCellWithIdentifier方法内部会先看缓存池中是否有该种类的cell,如果没有再判断是否已经注册,如果已经注册过,该方法会创建一个新的cell并返回,所以该方法返回值永远不为空,所以就可以省去if(cell== nil)判断了,但是这种方法有个不好的地方是不能改变单元格的样式,但是这不影响自定义的cell,需要注意的是注册单元格只需要注册一次就够了,所以注册单元格一般放在viewDidLoad方法中

const NSString *ID = NSStringFromClass([self class]);
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
// 共同的设置
}

索引条:位于UITableView的最右侧,

-(BOOL)prefersStatusBarHidden{return true;} // 隐藏状态条,UIViewController中的方法
// tableView段索引标题,只需要数组中的元素和段标题的值相等即可,系统会自动计算offset进行滚动的
-(NSArray