原创:知识点总结性文章
创作不易,请珍惜,之后会持续更新,不断完善
个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈哈,这些文章记录了我的IOS成长历程,希望能与大家一起进步
温馨提示:由于简书不支持目录跳转,大家可通过command + F 输入目录标题后迅速寻找到你所需要的内容
目录
- 一、UIWindow与UIView
- 二、UIControl
- 1、UISlider
- 2、SegmentedControl
- 3、UISwitch
- 4、UIActivityIndicatorView
- 5、UIProgressView
- 6、UIRefreshControl
- 三、Input View
- 1、UILabel
- 2、UITextField
- 3、UITextView
- 三、UIScrollView
- 1、创建滚动视图
- 2、UIScrollViewDelegate
- 四、UITableView
- 1、PersonTableViewCell.h文件
- 2、PersonTableViewCell.m文件
- 3、编辑 TableView
- 4、UITableViewDataSource
- 5、UITableViewDelegate
- 6、配置数据源
- 五、UICollectionView
- 1、通讯录cell的.h文件
- 2、集合数据源
- 3、UICollectionViewDataSource
- 4、UICollectionViewDelegate
- 六、UIPickerView
- 1、创建选择器视图
- 2、UIPickerViewDataSource
- 3、UIPickerViewDelegate
- 七、AlertView
- 1、创建选择面板
- 2、利用KVC方法进行UIAlertController属性的自定义
- 3、为UIAlertController添加文本框
- 八、UISearchBar
- 1、UISearchBar的属性
- 2、UISearchBar的方法
- 3、UISearchBarDelegate代理方法
- 九、UINavigationController
- 1、配置返回按钮
- 2、配置导航栏
- 3、UITabBarController
- 十、GestureRecognizer
- 1、Tap: 点击
- 2、Swipe: 轻扫
- 3、LongPress: 长按
- 4、Pan: 平移
- 5、ScreenEdgePan: 屏幕边缘平移
- 6、Pinch: 捏合
- 7、Rotation: 旋转
- 8、支持多个UIGestureRecongnizer共存
- 9、响应屏幕触摸
- 10、运动事件监听
- 11、手势谁先响应
- 12、手势提供的属性和方法
- Demo
- 参考文献
一、UIWindow与UIView
UIWindow
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
UIView
- (void)setNeedsLayout;
- (void)layoutIfNeeded;
- (void)layoutSubviews;
- (void)removeFromSuperview;
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
self.view.subviews
[self.view exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
CALayer
CALayer *layer;
layer.borderWidth
layer.borderColor
二、UIControl
1、UISlider
a、创建滑条视图
- (void)createSliderView
{
UISlider *horizontalSlider = [[UISlider alloc] initWithFrame:CGRectZero];
horizontalSlider.minimumValue = 10;
horizontalSlider.maximumValue = 100;
[horizontalSlider addTarget:self action:@selector(horizontalSliderChanged:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:horizontalSlider];
[horizontalSlider mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
make.height.equalTo(@44);
make.left.equalTo(self.view.mas_left).offset(30);
make.right.equalTo(self.view.mas_right).offset(-30);
}];
UISlider *verticalSlider = [[UISlider alloc] initWithFrame:CGRectZero];
// 旋转90度
CGAffineTransform transform = verticalSlider.transform;
transform = CGAffineTransformRotate(transform, -M_PI/2);
verticalSlider.transform = transform;
verticalSlider.minimumValue = 10;
verticalSlider.maximumValue = 100;
[verticalSlider addTarget:self action:@selector(verticalSliderChanged:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:verticalSlider];
[verticalSlider mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(280);
make.height.equalTo(@44);
make.left.equalTo(self.view.mas_left).offset(30);
make.right.equalTo(self.view.mas_right).offset(-30);
}];
}
b、事件方法
- (void)horizontalSliderChanged:(id)sender
{
UISlider *slider = sender;
NSLog(@"水平滑条值改变:%f", slider.value);
}
- (void)verticalSliderChanged:(id)sender
{
UISlider *slider = sender;
NSLog(@"垂直滑条值改变: %f", slider.value);
}
c、输出结果
2020-10-13 15:36:17.451947+0800 BasicGrammarDemo[45225:2120947] 水平滑条值改变:58.211006
2020-10-13 15:36:17.822776+0800 BasicGrammarDemo[45225:2120947] 水平滑条值改变:58.211006
2020-10-13 15:36:18.509124+0800 BasicGrammarDemo[45225:2120947] 垂直滑条值改变: 10.000000
2020-10-13 15:36:18.530712+0800 BasicGrammarDemo[45225:2120947] 垂直滑条值改变: 12.110093
2、SegmentedControl
a、创建SegmentedControl视图
- (void)createSegmentedControl
{
UISegmentedControl *segmentControl = [[UISegmentedControl alloc] initWithItems:@[@"item1", @"item2", @"item3"]];
segmentControl.selectedSegmentIndex = 1;
[segmentControl addTarget:self action:@selector(segmentControlChanged:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:segmentControl];
[segmentControl mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(60);
make.height.equalTo(@44);
make.left.equalTo(self.view.mas_left).offset(20);
make.right.equalTo(self.view.mas_right).offset(-100);
}];
}
b、事件方法
- (void)segmentControlChanged:(id)sender
{
UISegmentedControl *segmentControl = sender;
NSLog(@"segmentControl值改变:%@", @(segmentControl.selectedSegmentIndex));
}
c、输出结果
2020-10-13 15:35:23.543024+0800 BasicGrammarDemo[45161:2117200] segmentControl值改变:0
3、UISwitch
a、创建开关视图
- (void)createSwitchView
{
UISwitch *switcher = [[UISwitch alloc] initWithFrame:CGRectZero];
[switcher addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:switcher];
[switcher mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(120);
make.height.equalTo(@44);
make.left.equalTo(self.view.mas_left).offset(20);
make.width.equalTo(@100);
}];
}
b、输出结果
2020-10-13 16:06:16.290280+0800 BasicGrammarDemo[45707:2145882] 开关改变了:1
4、UIActivityIndicatorView
- (void)createActivityIndicatorView
{
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleMedium];
// 只能设置中心,不能设置大小
activityIndicator.center = CGPointMake(200.0f, 200.0f);
// 改变圈圈的颜色为红色
activityIndicator.color = [UIColor redColor];
// 开始旋转
[activityIndicator startAnimating];
// 结束旋转
[activityIndicator stopAnimating];
// 添加指示器到导航栏
self.navigationItem.titleView = activityIndicator;
self.navigationItem.prompt = @"正在使出吃奶的劲加载中...";
// 停止指示器控件本应该调用 stopAnimating 方法,但放在导航栏项目中的活动指示器控件有所不同
// 要移除这个控件,让原来的title内容显示出来
self.navigationItem.titleView = nil;
self.navigationItem.prompt = nil;
[self.view addSubview:activityIndicator];
}
5、UIProgressView
self.progressView.progress = self.progressView.progress + 0.1;
if (self.progressView.progress == 1.0)
{
[self.timer invalidate];
}
6、UIRefreshControl
self.collectionView.alwaysBounceVertical = YES;// 必须打开
self.refreshControl.tintColor = [UIColor grayColor];
[self.refreshControl addTarget:self action:@selector(urlRequestForCollection) forControlEvents:UIControlEventValueChanged];
[self.collectionView addSubview:self.refreshControl];
[weakSelf.refreshControl endRefreshing];// 结束刷新
三、Input View
1、UILabel
- (void)createLabelView
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(150, 100, 100, 50)];
// 位置位于视图中央
label.center = self.view.center;
// 自适应大小的方法,即标签的大小由字体的大小长度决定
// 这个打开后会让label不再显示,慎用!!!
// [label sizeToFit];
// 设置字体大小是否适应label宽度
label.adjustsFontSizeToFitWidth = YES;
// 设置label的换行模式为根据单词进行换行
label.lineBreakMode = NSLineBreakByWordWrapping;
// 设置label显示几行,0表示可以有无限行
label.numberOfLines = 0;
// 设置文本是否高亮和高亮时的颜色
label.highlighted = YES;
label.highlightedTextColor = [[UIColor orangeColor] colorWithAlphaComponent:0.5];
// 设置阴影的颜色和阴影的偏移位置
label.shadowColor = [UIColor redColor];
label.shadowOffset = CGSizeMake(1.0, 1.9);
// 设置label中的文字是否可变,默认值是YES
label.enabled = YES;
// 如果adjustsFontSizeToFitWidth属性设置为YES,这个属性就来控制文本基线的行为
// 将文本缩小到基于原始基线的位置时使用,默认不使用
label.baselineAdjustment = UIBaselineAdjustmentNone;
// 设置背景色为透明
label.backgroundColor = [UIColor clearColor];
// 设置label的旋转角度
label.transform = CGAffineTransformMakeRotation(0.2);
// 让label自适应里面的文字,自动调整宽度和高度
NSString *string = @"天地之间隐有梵音";
[string boundingRectWithSize:CGSizeMake(320, 2000) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16]} context:nil];
// 让UILabel具有链接功能
// 如果我并没有安装app那它就会失败,同时会调用safari来打开这个链接
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http:baidu.com"] options:@{UIApplicationOpenURLOptionUniversalLinksOnly : @YES} completionHandler:nil];
// 让label显示出来
label.backgroundColor = [UIColor blackColor];
label.text = string;
[self.view addSubview:label];
}
2、UITextField
a、创建textField视图
- (void)createTextFieldView
{
self.passwordTextField = [[UITextField alloc] initWithFrame:CGRectZero];
self.passwordTextField.borderStyle = UITextBorderStyleRoundedRect;// 圆角矩形
self.passwordTextField.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 22, 22)];// 左视图大小
self.passwordTextField.leftView.backgroundColor = [UIColor redColor];// 左视图背景颜色
self.passwordTextField.leftViewMode = UITextFieldViewModeAlways;// 左视图总是显示
self.passwordTextField.clearButtonMode = UITextFieldViewModeWhileEditing;// 显示清空按钮
self.passwordTextField.secureTextEntry = YES;// 加密显示,该属性通常用于设置密码输入框
self.passwordTextField.clearsOnBeginEditing = YES;// 当重复开始编辑时候清除文字
// 返回类型:Default换行 Go前往 Google/Search搜索 Join加入 Next下一项 Route路线 Send发送 Done完成 Continue继续
self.passwordTextField.returnKeyType = UIReturnKeySearch;
// 设置弹出视图inputView,即弹出的不是键盘而是这个视图
// 默认的整个键盘宽度,只有设置高度会有用
self.passwordTextField.inputView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"luckcoffee.JPG"]];
// 纵向对齐方式,默认是居中
self.passwordTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
// 设置调整文字大小以适配宽度(即输入不下时缩小文字,实在缩小不了了,就向后滚动),默认是向右滚动的
self.passwordTextField.adjustsFontSizeToFitWidth = YES;
// 设置最小字号,和上面有关,即小于这个字号的时候就不缩小了,直接向右滚动
self.passwordTextField.minimumFontSize = 2;
// 设置字母大小样式 AllCharacters-所有字母大写 Words-单词首字母大写 Sentences-句首字母大写
self.passwordTextField.autocapitalizationType = UITextAutocapitalizationTypeSentences;
self.passwordTextField.delegate = self;
[self.passwordTextField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
[self.view addSubview:self.passwordTextField];
[self.passwordTextField mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(60);
make.height.equalTo(@44);
make.left.equalTo(self.view.mas_left).offset(20);
make.right.equalTo(self.view.mas_right).offset(-20);
}];
}
b、UITextFieldDelegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField// 是否可以编辑
{
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField// 开始编辑
{
NSLog(@"开始编辑");
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField// 是否应该结束编辑
{
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField// 结束编辑
{
NSLog(@"结束编辑");
}
- (void)textFieldDidChange:(UITextField *)textField// 获取编辑完成的文本
{
NSLog(@"获取编辑完成的文本 %@", textField.text);
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string// 编辑过程中会不断调用
{
if (string.length > 0)// 有输入字符
{
if ([string isEqualToString:@"0"])// 输入0则允许改变,可以继续输入
{
return YES;
}
return NO;
}
return YES;
}
- (BOOL)textFieldShouldClear:(UITextField *)textField// 是否可以清空
{
// 点击清除按钮,应该同时将本地数据源里的文本清空
if (textField == self.passwordTextField)
{
self.password = @"";
}
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField// 是否可以返回
{
return YES;
}
输出结果
2020-10-13 16:09:15.357943+0800 BasicGrammarDemo[45707:2145882] 开始编辑
2020-10-13 16:09:16.478273+0800 BasicGrammarDemo[45707:2145882] 获取编辑完成的文本 0
2020-10-13 16:09:16.643681+0800 BasicGrammarDemo[45707:2145882] 获取编辑完成的文本 00
3、UITextView
a、创建textView视图
- (void)createTextView
{
self.textView = [[UITextView alloc] initWithFrame:CGRectZero];
self.textView.layer.borderColor = [UIColor blackColor].CGColor;
self.textView.layer.borderWidth = 1.0;
self.textView.delegate = self;
self.textView.text = @"孟子,既然男女授受不亲,嫂子掉到水里,要不要伸手去拉,假如“礼”是那么重要,人命就不要了吗?,不去救嫂子则“是豺狼也”,但这要怪嫂子干吗要掉进水里。他没有说戴上了手套再去拉嫂子,唯一的不幸就是自己的无能,对数学家来说,只要他能证明费尔马定理,就可以获得全球数学家的崇敬,自己也可以得到极大的快感,问题在于你证不出来。";
[self.view addSubview:self.textView];
[self.textView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(120);
make.height.equalTo(@100);
make.left.equalTo(self.view.mas_left).offset(20);
make.right.equalTo(self.view.mas_right).offset(-20);
}];
}
b、UITextViewDelegate
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView// 是否可以编辑
{
return YES;
}
- (BOOL)textViewShouldEndEditing:(UITextView *)textView// 是否应该结束编辑
{
return YES;
}
- (void)textViewDidBeginEditing:(UITextView *)textView
{
NSLog(@"开始编辑");
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
NSLog(@"结束编辑");
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text// 编辑过程中会不断调用
{
return YES;
}
- (void)textViewDidChange:(UITextView *)textView// 获取编辑完成的文本
{
NSLog(@"获取编辑完成的文本 %@", textView.text);
}
- (void)textViewDidChangeSelection:(UITextView *)textView// 编辑完成的文本
{
NSLog(@"改变了选中部分的文本");
}
输出结果
2020-10-13 17:25:36.642017+0800 BasicGrammarDemo[55396:2252994] 开始编辑
2020-10-13 17:25:36.645211+0800 BasicGrammarDemo[55396:2252994] 改变了选中部分的文本
2020-10-13 17:25:47.733527+0800 BasicGrammarDemo[55396:2252994] 获取编辑完成的文本 孟子,既然男女授受不亲,嫂子掉到水里,要不要伸手去拉,假如“礼”
三、UIScrollView
1、创建滚动视图
- (void)createScrollView
{
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
self.scrollView.delegate = self;
self.scrollView.pagingEnabled = YES;// 是否支持翻页
self.scrollView.showsHorizontalScrollIndicator = YES;// 展示水平滚动条
self.scrollView.showsVerticalScrollIndicator = NO;// 展示垂直滚动条
self.scrollView.minimumZoomScale = 0.5;// 最小化
self.scrollView.maximumZoomScale = 2.0;// 最大化
self.scrollView.scrollsToTop = YES;// 要不要返回顶部
self.scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;// 滚动条颜色
CGSize viewSize = self.view.bounds.size;
self.scrollView.contentSize = CGSizeMake(viewSize.width*3, viewSize.height);// 内容为屏幕3倍用于横向滑动
[self.view addSubview:self.scrollView];
[self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
make.left.equalTo(self.view.mas_left);
make.right.equalTo(self.view.mas_right);
}];
self.pageControl = [[UIPageControl alloc] initWithFrame:CGRectZero];
self.pageControl.numberOfPages = 3;// 3页
self.pageControl.pageIndicatorTintColor = [UIColor colorWithWhite:1 alpha:0.5];// 小点的颜色
self.pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];// 当前点的颜色
[self.view addSubview:self.pageControl];
[self.pageControl mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom).offset(-20);
make.height.equalTo(@44);
make.left.equalTo(self.view.mas_left);
make.right.equalTo(self.view.mas_right);
}];
// 创建红、蓝、绿三个页面
UIView *redView = [self createScrollViewSubViewWithOffset:0];
redView.backgroundColor = [UIColor redColor];
UIView *blueView = [self createScrollViewSubViewWithOffset:viewSize.width];
blueView.backgroundColor = [UIColor blueColor];
UIView *greenView = [self createScrollViewSubViewWithOffset:viewSize.width*2];
greenView.backgroundColor = [UIColor greenColor];
}
- (UIView *)createScrollViewSubViewWithOffset:(CGFloat)offsetX
{
CGSize viewSize = self.view.bounds.size;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(offsetX, 0, viewSize.width, viewSize.height)];
[self.scrollView addSubview:view];
return view;
}
2、UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView// 滚动了
{
NSLog(@"偏移量:%@", @(scrollView.contentOffset.x));
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView// 结束滚动
{
CGFloat offsetX = scrollView.contentOffset.x;
NSLog(@"结束滚动时候在X轴的偏移量:%@", @(offsetX));
// 计算当前页数
NSInteger index = offsetX / scrollView.frame.size.width;
self.pageControl.currentPage = index;
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView// 需要缩放的视图
{
CGFloat offsetX = scrollView.contentOffset.x;
NSInteger index = offsetX / scrollView.frame.size.width;
return scrollView.subviews[index];
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView// 缩放比例
{
NSLog(@"缩放了 %@", @(scrollView.zoomScale));
}
输出结果
2020-10-13 17:43:22.163863+0800 BasicGrammarDemo[55573:2261834] 缩放了 0.7947149384108813
2020-10-13 17:43:22.241076+0800 BasicGrammarDemo[55573:2261834] 偏移量:-23.19056305867597
2020-10-13 17:45:23.062048+0800 BasicGrammarDemo[55573:2261834] 结束滚动时候在X轴的偏移量:228.3333333333333
四、UITableView
1、PersonTableViewCell.h文件
@interface PersonTableViewCell : UITableViewCell
@property (nonatomic, strong, readonly) UILabel *nameLabel;// 姓名
@property (nonatomic, strong, readonly) UILabel *namePinyinLabel;// 姓名拼音
@property (nonatomic, strong, readonly) UILabel *mobileLabel;// 手机
@property (nonatomic, strong, readonly) UILabel *introductionLabel;// 介绍
@end
2、PersonTableViewCell.m文件
a、初始化方法
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
[self createSubViews];
[self createSubViewsConstraints];
}
return self;
}
b、添加子视图
- (void)createSubViews
{
self.nameLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.nameLabel.textAlignment = NSTextAlignmentLeft;
[self.contentView addSubview:self.nameLabel];
self.namePinyinLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.namePinyinLabel.textAlignment = NSTextAlignmentRight;
[self.contentView addSubview:self.namePinyinLabel];
self.mobileLabel = [[UILabel alloc] initWithFrame:CGRectZero];
[self.contentView addSubview:self.mobileLabel];
self.introductionLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.introductionLabel.numberOfLines = 0;
[self.contentView addSubview:self.introductionLabel];
}
c、添加约束
- (void)createSubViewsConstraints
{
[self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.contentView.mas_top).offset(10);
make.height.equalTo(@30);
make.left.equalTo(self.contentView.mas_left).offset(20);
make.right.equalTo(self.contentView.mas_right).offset(-20);
}];
[self.namePinyinLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.nameLabel.mas_top);
make.bottom.equalTo(self.nameLabel.mas_bottom);
make.left.equalTo(self.contentView.mas_left).offset(20);
make.right.equalTo(self.contentView.mas_right).offset(-20);
}];
[self.mobileLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.nameLabel.mas_bottom).offset(10);
make.height.equalTo(@30);
make.left.equalTo(self.contentView.mas_left).offset(20);
make.right.equalTo(self.contentView.mas_right).offset(-20);
}];
[self.introductionLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.mobileLabel.mas_bottom).offset(10);
make.bottom.equalTo(self.contentView.mas_bottom).offset(-10);
make.left.equalTo(self.contentView.mas_left).offset(20);
make.right.equalTo(self.contentView.mas_right).offset(-20);
}];
}
3、编辑 TableView
a、为导航栏添加编辑按钮
- (void)configureNavigationbar
{
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"编辑" style:UIBarButtonItemStylePlain target:self action:@selector(editTable)];
self.editFinished = YES;
}
b、点击导航栏的编辑按钮
- (void)editTable
{
if (self.isEditFinished)
{
self.editFinished = NO;
self.navigationItem.rightBarButtonItem.title = @"完成";
self.tableView.editing = YES;// 正在编辑
}
else
{
self.editFinished = YES;
self.navigationItem.rightBarButtonItem.title = @"编辑";
self.tableView.editing = NO;// 非编辑状态
}
}
c、创建TableView
- (void)createTableView
{
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
[self.tableView registerClass:[PersonTableViewCell class] forCellReuseIdentifier:TableCellReuseIdentifier];
self.tableView.delegate = self;
self.tableView.dataSource = self;
// 不显示右侧滑块
self.tableView.showsVerticalScrollIndicator = NO;
// 分割线
self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
// 表头表尾高度
self.tableView.sectionHeaderHeight = 20;
self.tableView.sectionFooterHeight = 20;
// 弹动
self.tableView.bounces = NO;
// 多选模式
// self.tableView.allowsSelection = YES;
// self.tableView.allowsSelectionDuringEditing = YES;
// self.tableView.allowsMultipleSelection = YES;
// self.tableView.allowsMultipleSelectionDuringEditing = YES;
[self.view addSubview:self.tableView];
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
make.left.equalTo(self.view.mas_left);
make.right.equalTo(self.view.mas_right);
}];
}
4、UITableViewDataSource
a、section 数量
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.personTableArray.count;
}
b、cell 数量
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.personTableArray[section].count;
}
c、cell 样式
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
PersonTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TableCellReuseIdentifier forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;// 选中风格
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;// 右指示器
//cell.accessoryView = imageBtn;// cell可以设置装饰图
// cell自带imageView属性、text属性、detailTextLabel属性
cell.detailTextLabel.text = @"更多";
PersonModel *personModel = self.personTableArray[indexPath.section][indexPath.row];
cell.nameLabel.text = personModel.name;
cell.namePinyinLabel.text = personModel.namePinyin;
cell.mobileLabel.text = personModel.mobile;
cell.introductionLabel.text = personModel.introduction;
return cell;
}
d、SectionHeader 标题
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return self.sectionIndexTitles[section];// 索引数组
}
e、能否编辑 cell
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return (indexPath.section > 0);// 除第一节外都可编辑
}
f、能否移动 cell
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return (indexPath.section == 1);// 第二节可以移动cell
}
g、TableView的右边索引列的标题
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return self.sectionIndexTitles;
}
f、TableView的右边索引列的位置,好像没什么用
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return index;
}
g、支持插入和删除 cell
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// 从数据源里移除当前cell的数据
NSMutableArray *personArray = self.personTableArray[indexPath.section];
[personArray removeObjectAtIndex:indexPath.row];
// 移除完后当前Section不再拥有cell了
if (personArray.count == 0)
{
// 移除当前Section的数据和索引标题
[self.personTableArray removeObjectAtIndex:indexPath.section];
[self.sectionIndexTitles removeObjectAtIndex:indexPath.section];
}
// 从视图中移除当前cell
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
h、支持移动 cell
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
// 从数据源中移除初始cell的数据
NSMutableArray *sourcePersonArray = self.personTableArray[sourceIndexPath.section];
PersonModel *sourcePersonModel = sourcePersonArray[sourceIndexPath.row];
[sourcePersonArray removeObjectAtIndex:sourceIndexPath.row];
self.personTableArray[sourceIndexPath.section] = sourcePersonArray;
// 从数据源中向目的cell添加数据
NSMutableArray *destinationPersonArray = self.personTableArray[destinationIndexPath.section];
[destinationPersonArray insertObject:sourcePersonModel atIndex:destinationIndexPath.row];
self.personTableArray[destinationIndexPath.section] = destinationPersonArray;
}
5、UITableViewDelegate
a、选中 cell
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"didSelectRowAtIndexPath %@", indexPath);
}
b、编辑风格
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
c、删除确认按钮的标题
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return @"删除";
}
6、配置数据源
- (void)readTablePersonData
{
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"person" withExtension:@"json"];
NSData *fileData = [NSData dataWithContentsOfURL:fileURL options:NSDataReadingMappedIfSafe error:nil];
NSArray<NSDictionary *> *persons = [NSJSONSerialization JSONObjectWithData:fileData options:NSJSONReadingMutableContainers error:nil];
// json to model
NSMutableArray<PersonModel *> *personModelArray = [NSMutableArray array];
[persons enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
PersonModel *personModel = [[PersonModel alloc] init];
personModel.name = obj[@"name"];
personModel.namePinyin = obj[@"pinyin"];
personModel.nameFirstLetter = obj[@"first_letter"];
personModel.mobile = obj[@"mobile"];
personModel.introduction = obj[@"introduction"];
[personModelArray addObject:personModel];
}];
// 按照字母顺序进行排序
[personModelArray sortUsingComparator:^NSComparisonResult(PersonModel *obj1, PersonModel *obj2) {
return [obj1.namePinyin compare:obj2.namePinyin];
}];
// 按拼音首字母拆分,顺序遍历
NSMutableArray<NSMutableArray<PersonModel *> *> *personDataArray = [NSMutableArray array];
NSMutableArray<NSString *> *sectionIndexArray = [NSMutableArray array];
NSMutableArray<PersonModel *> *personArray = [NSMutableArray array];
NSInteger count = personModelArray.count;
for (int i=0; i<count; I++)
{
PersonModel *personModel = personModelArray[I];
if (![sectionIndexArray containsObject:personModel.nameFirstLetter])// 不包含的首字母则需要新的array容纳
{
// 将该首字母添加到索引数组
[sectionIndexArray addObject:personModel.nameFirstLetter];
if (personArray.count > 0)// array代表的上一个section存在model
{
// personDataArray代表[Section[row]]
[personDataArray addObject:[personArray mutableCopy]];
// 清空旧的model,成为新array
[personArray removeAllObjects];
}
}
// 首字母已经被包含,说明是该model处于同一个section,则添加到array即可
[personArray addObject:personModel];
}
// 添加最后一个personArray
[personDataArray addObject:[personArray copy]];
// 重新加载table
self.personTableArray = personDataArray;
self.sectionIndexTitles = sectionIndexArray;
[self.tableView reloadData];
}
五、UICollectionView
NSString * const CollectionCellReuseIdentifier = @"cell";
@interface ViewController ()<UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
// 数据源
@property (nonatomic, strong) NSArray *personArray;
// 集合视图
@property (nonatomic, strong) UICollectionView *collectionView;
@end
1、创建集合视图
- (void)createCollectionView
{
// 创建集合视图的布局
CGSize viewSize = self.view.bounds.size;
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(viewSize.width/2 - 10, viewSize.height);
layout.minimumLineSpacing = 10;// Item之间的上下间距
layout.minimumInteritemSpacing = 10;// Item之间的左右间距
layout.scrollDirection = UICollectionViewScrollDirectionVertical;// 滚动方向
// 创建集合视图
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
self.collectionView.backgroundColor = [UIColor whiteColor];// 默认没有颜色,会渲染成黑色
[self.collectionView registerClass:[PersonCollectionViewCell class] forCellWithReuseIdentifier:CollectionCellReuseIdentifier];
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
[self.view addSubview:self.collectionView];
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
make.left.equalTo(self.view.mas_left);
make.right.equalTo(self.view.mas_right);
}];
}
2、集合数据源
- (void)readPersonData
{
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"person" withExtension:@"json"];
NSData *fileData = [NSData dataWithContentsOfURL:fileURL options:NSDataReadingMappedIfSafe error:nil];
NSArray<NSDictionary *> *persons = [NSJSONSerialization JSONObjectWithData:fileData options:NSJSONReadingMutableContainers error:nil];
// json to model
NSMutableArray<PersonModel *> *personArray = [NSMutableArray array];
[persons enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
PersonModel *personModel = [[PersonModel alloc] init];
personModel.name = obj[@"name"];
personModel.namePinyin = obj[@"pinyin"];
personModel.nameFirstLetter = obj[@"first_letter"];
personModel.mobile = obj[@"mobile"];
personModel.introduction = obj[@"introduction"];
[personArray addObject:personModel];
}];
// 按照字母顺序进行排序
[personArray sortUsingComparator:^NSComparisonResult(PersonModel *obj1, PersonModel *obj2) {
return [obj1.namePinyin compare:obj2.namePinyin];
}];
// 重新加载页面
self.personArray = personArray;
[self.collectionView reloadData];
}
3、UICollectionViewDataSource
Item数目
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.personArray.count;
}
Item内容
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
PersonCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CollectionCellReuseIdentifier forIndexPath:indexPath];
PersonModel *personModel = self.personArray[indexPath.item];
cell.nameLabel.text = personModel.name;
cell.namePinyinLabel.text = personModel.namePinyin;
cell.mobileLabel.text = personModel.mobile;
cell.introductionLabel.text = personModel.introduction;
return cell;
}
4、UICollectionViewDelegate
选中Item
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"选中了Item");
}
5、UICollectionViewDelegateFlowLayout
Item尺寸大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
// 页面宽度一半 - 10 作为Item宽度
CGSize viewSize = self.view.bounds.size;
CGFloat width = viewSize.width/2 - 10;
// 根据字号、宽度、内容来估计introduction的高度
PersonModel *personModel = self.personArray[indexPath.row];
CGSize size = [personModel.introduction boundingRectWithSize:CGSizeMake(width - 24, 2000) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:15.0]} context:nil].size;
// 返回Item尺寸大小
return CGSizeMake(width, size.height + 160);
}
六、UIPickerView
1、创建选择器视图
- (void)createPickerView
{
self.pickerView = [[UIPickerView alloc] initWithFrame:CGRectZero];
self.pickerView.delegate = self;
self.pickerView.dataSource = self;
[self.view addSubview:self.pickerView];
[self.pickerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
make.height.equalTo(@200);
make.left.equalTo(self.view.mas_left);
make.right.equalTo(self.view.mas_right);
}];
self.datePicker = [[UIDatePicker alloc] initWithFrame:CGRectZero];
[self.datePicker addTarget:self action:@selector(datePickerChanged:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:self.datePicker];
[self.datePicker mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(300);
make.height.equalTo(@200);
make.left.equalTo(self.view.mas_left);
make.right.equalTo(self.view.mas_right);
}];
}
- (void)datePickerChanged:(id)sender
{
UIDatePicker *datePicker = sender;
NSLog(@"选择的日期为:%@", datePicker.date);
}
2、UIPickerViewDataSource
转盘数目
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
每个转盘的行数
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return 5;
}
3、UIPickerViewDelegate
a、每个转盘的宽度
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
{
return self.view.bounds.size.width/2;
}
b、转盘中每一行的高度
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
return 44.0;
}
c、每一行的标题
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return self.pickerData[component][row];
}
d、选择转盘
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSLog(@"选择的转盘为:%@, 选择的行数上的内容为:%@", @(component), self.pickerData[component][row]);
if (component == 0)// 滚动第一个转盘时候需要联动第二个转盘
{
[pickerView reloadComponent:1];
}
}
e、数据源
- (void)configuePickerData
{
NSArray *columnFirst = @[@"谢佳培", @"王德胜", @"白落梅", @"车行迟", @"林风眠"];
NSArray *columnSecond = @[@"IOS开发", @"院士", @"作家", @"虚构", @"画家"];
self.pickerData = @[columnFirst, columnSecond];
// 重新加载表盘
[self.pickerView reloadAllComponents];
}
输出结果
2020-10-13 18:12:46.186157+0800 BasicGrammarDemo[56013:2286395] 选择的转盘为:1, 选择的行数上的内容为:IOS开发
七、AlertView
1、创建选择面板
- (void)showActionSheetController
{
UIAlertController *actionSheetController = [UIAlertController alertControllerWithTitle:@"作家" message:@"每个人的名字都像一幅水墨画" preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"点击了取消");
}];
[actionSheetController addAction:cancelAction];
UIAlertAction *firstAction = [UIAlertAction actionWithTitle:@"查看白落梅" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"查看白落梅");
}];
[actionSheetController addAction:firstAction];
UIAlertAction *secondAction = [UIAlertAction actionWithTitle:@"查看丰子恺" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"查看丰子恺");
}];
[actionSheetController addAction:secondAction];
UIAlertAction *thirdAction = [UIAlertAction actionWithTitle:@"查看郁达夫" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"查看郁达夫");
}];
[actionSheetController addAction:thirdAction];
[self presentViewController:actionSheetController animated:YES completion:nil];
}
2、利用KVC方法进行UIAlertController属性的自定义
- (void)customAlert
{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"提示内容" preferredStyle:UIAlertControllerStyleAlert];
// 修改title
NSMutableAttributedString *alertControllerStr = [[NSMutableAttributedString alloc] initWithString:@"提示"];
[alertControllerStr addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, 2)];
[alertControllerStr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:17] range:NSMakeRange(0, 2)];
// 利用KVC方法进行UIAlertController属性的自定义
// 有时候使用第三方控件会带来很多不必要的代码量和bug,所以能用系统自带最好
[alertController setValue:alertControllerStr forKey:@"attributedTitle"];
// 修改message
NSMutableAttributedString *alertControllerMessageStr = [[NSMutableAttributedString alloc] initWithString:@"提示内容"];
[alertControllerMessageStr addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(0, 4)];
[alertControllerMessageStr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:20] range:NSMakeRange(0, 4)];
[alertController setValue:alertControllerMessageStr forKey:@"attributedMessage"];
// 常规按钮
UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"Default" style:UIAlertActionStyleDefault handler:nil];
// 销毁按钮
UIAlertAction *destructiveAction = [UIAlertAction actionWithTitle:@"Destructive" style:UIAlertActionStyleDestructive handler:nil];
// 取消按钮
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
[alertController addAction:defaultAction];
[alertController addAction:destructiveAction];
[alertController addAction:cancelAction];
[self presentViewController:alertController animated:YES completion:nil];
}
3、为UIAlertController添加文本框
- (void)textFieldForAlert
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"title" message:@"message" preferredStyle:UIAlertControllerStyleAlert];
// 添加文本框
[alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
// 设置键盘输入为数字键盘
textField.keyboardType = UIKeyboardTypeNumberPad;
textField.placeholder = @"请填写";
}];
// 添加取消按钮
UIAlertAction *cancelButton = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
// 取消
}];
[alert addAction: cancelButton];
// 添加确定按钮
UIAlertAction *confirmButton = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
// 文本框结束编辑,收起键盘
[[alert.textFields firstObject] endEditing:YES];
// 获取文本框填写的内容
NSString *meetingId = [alert.textFields firstObject].text;
if (meetingId.length > 12)
{
//[weakSelf showText:@"会议号过长"];
}
else
{
//[weakSelf enterVideoMeeting:meetingId];
}
}];
[alert addAction: confirmButton];
//显示
[self presentViewController:alert animated:YES completion:nil];
}
八、UISearchBar
1、UISearchBar的属性
// 搜索框风格
// UIBarStyleDefault 白色搜索框,灰色背景
// UIBarStyleBlack 黑色搜索框
@property(nonatomic) UIBarStyle barStyle;
// 搜索的文本
@property(nullable,nonatomic,copy) NSString *text;
// 搜索框顶部的提示信息
@property(nullable,nonatomic,copy) NSString *prompt;
// 占位符,默认nil, 若有值则在输入文本后消失
@property(nullable,nonatomic,copy) NSString *placeholder;
// 搜索框右侧是否显示图书按钮
@property(nonatomic) BOOL showsBookmarkButton; 📖
//搜索框右侧是否显示取消按钮
@property(nonatomic) BOOL showsCancelButton; Cancel
//搜索框右侧是否显示搜索结果按钮
@property(nonatomic) BOOL showsSearchResultsButton; ⤓
// 搜索结果按钮为选中状态
@property(nonatomic, getter=isSearchResultsButtonSelected) BOOL searchResultsButtonSelected;☑️
// 风格颜色,可用于修改输入框的光标颜色,取消按钮和选择栏被选中时候都会变成设置的颜色
@property(null_resettable, nonatomic,strong) UIColor *tintColor; //|线条的颜色
// 搜索框背景颜色
@property(nullable, nonatomic,strong) UIColor *barTintColor;
// 搜索框样式
// UISearchBarStyleMinimal:不显示背景,系统自带的背景色无效,自定义的有效,常用在Calendar, Notes and Music
// UISearchBarStyleProminent、UISearchBarStyleDefault:显示背景,常用在my Mail, Messages and Contacts
@property (nonatomic) UISearchBarStyle searchBarStyle
// 选择按钮视图的按钮标题
@property(nullable, nonatomic,copy) NSArray<NSString *> *scopeButtonTitles ;
// 选中的按钮下标值 ,默认 0. 如果超出范围则忽略
@property(nonatomic) NSInteger selectedScopeButtonIndex ;
// 是否显示搜索栏的附件选择按钮视图
@property(nonatomic) BOOL showsScopeBar;
// 搜索框背景图片
@property(nullable, nonatomic,strong) UIImage *backgroundImage;
// 搜索框附属分栏条的背景颜色
@property(nullable, nonatomic,strong) UIImage *scopeBarBackgroundImage;
// 搜索框中文本框的背景偏移量
@property(nonatomic) UIOffset searchFieldBackgroundPositionAdjustment;
// 搜索框中文本框的文本偏移量
@property(nonatomic) UIOffset searchTextPositionAdjustment;
2、UISearchBar的方法
// 设置是否动画效果的显示或隐藏取消按钮
- (void)setShowsCancelButton:(BOOL)showsCancelButton animated:(BOOL)animated
// 1.设置搜索框背景图片
- (void)setBackgroundImage:(nullable UIImage *)backgroundImage forBarPosition:(UIBarPosition)barPosition barMetrics:(UIBarMetrics)barMetrics
// 获取搜索框背景图片
- (nullable UIImage *)backgroundImageForBarPosition:(UIBarPosition)barPosition barMetrics:(UIBarMetrics)barMetrics
// 2.设置选择按钮视图的背景图片
- (void)setScopeBarButtonBackgroundImage:(nullable UIImage *)backgroundImage forState:(UIControlState)state
// 获取选择按钮视图的背景图片
- (nullable UIImage *)scopeBarButtonBackgroundImageForState:(UIControlState)state
// 3.设置搜索框文本框的背景图片
- (void)setSearchFieldBackgroundImage:(nullable UIImage *)backgroundImage forState:(UIControlState)state
// 获取搜索框文本框的背景图片
- (nullable UIImage *)searchFieldBackgroundImageForState:(UIControlState)state
// 4.设置搜索框的图标
- (void)setImage:(nullable UIImage *)iconImage forSearchBarIcon:(UISearchBarIcon)icon state:(UIControlState)state;
// 获取搜索框的图标
- (nullable UIImage *)imageForSearchBarIcon:(UISearchBarIcon)icon state:(UIControlState)state;
// 5.设置选择按钮视图的分割线图片
- (void)setScopeBarButtonDividerImage:(nullable UIImage *)dividerImage forLeftSegmentState:(UIControlState)leftState rightSegmentState:(UIControlState)rightState;
// 获取选择按钮视图的分割线图片
- (nullable UIImage *)scopeBarButtonDividerImageForLeftSegmentState:(UIControlState)leftState rightSegmentState:(UIControlState)rightState;
// 6.设置选择按钮视图的标题样式
- (void)setScopeBarButtonTitleTextAttributes:(nullable NSDictionary<NSString *, id> *)attributes forState:(UIControlState)state;
// 获取选择按钮视图的标题样式
- (nullable NSDictionary<NSString *, id> *)scopeBarButtonTitleTextAttributesForState:(UIControlState)state
// 设置搜索框图标的偏移量
- (void)setPositionAdjustment:(UIOffset)adjustment forSearchBarIcon:(UISearchBarIcon)icon;
// 获取搜索框图标的偏移量
- (UIOffset)positionAdjustmentForSearchBarIcon:(UISearchBarIcon)icon;
3、UISearchBarDelegate代理方法
// 将要开始编辑文本时会调用该方法,返回 NO 将不会变成第一响应者
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar;
// 开始输入文本会调用该方法
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar;
// 将要结束编辑文本时会调用该方法,返回 NO 将不会释放第一响应者
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar;
// 结束编辑文本时调用该方法
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar;
// 文本改变会调用该方法(包含clear文本)
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText;
// 文字改变前会调用该方法,返回NO则不能加入新的编辑文字
- (BOOL)searchBar:(UISearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text ;
// 键盘上的搜索按钮点击的会调用该方法
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar;
// 搜索框右侧图书按钮点击会调用该方法
- (void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar ;
// 点击取消按钮会调用该方法
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar;
// 搜索结果列表按钮被按下会调用该方法
- (void)searchBarResultsListButtonClicked:(UISearchBar *)searchBar ;
// 搜索框的附属按钮视图中切换按钮会调用该方法
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope;
九、UINavigationController
1、配置返回按钮
- (void)createBackBarButton
{
// 自定义后退按钮的文字和颜色
// 如果不想显示文字,直接"",就会单独显示一个系统的返回箭头图标
// 必须放在触发push的那个页面才起作用
// 设置返回按钮的属性
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] init];
NSMutableDictionary *backTextAttrs = [NSMutableDictionary dictionary];
backTextAttrs[NSFontAttributeName] = [UIFont fontWithName:@"GillSans-SemiBoldItalic" size:20];// 字号
[backItem setTitleTextAttributes:backTextAttrs forState:UIControlStateHighlighted];// 高亮状态
backItem.title = @"返回";
self.navigationItem.backBarButtonItem = backItem;
}
2、配置导航栏
- (void)createNavigationController
{
self.navigationItem.title = @"详情界面";
// 使用图片作为导航栏标题
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"luckcoffee.JPG"]];
// 导航栏右边按钮添加文本
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"编辑" style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.rightBarButtonItem = item;
self.navigationItem.rightBarButtonItems = @[item,item];// 数组
// 导航栏右边按钮添加图片后仍然使按钮保持原来的系统颜色
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:@"luckcoffee.JPG"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:nil action:nil];
// 设置导航栏标题的属性
NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary];
textAttrs[NSForegroundColorAttributeName] = [UIColor redColor];// 字体颜色
textAttrs[NSFontAttributeName] = [UIFont fontWithName:@"GillSans-SemiBoldItalic" size:18];// 字号
self.navigationController.navigationBar.titleTextAttributes = textAttrs;
// 设置导航栏的背景颜色
[self.navigationController.navigationBar setBarTintColor:[UIColor greenColor]];
[self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]}];
// 给导航栏添加背景图片
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"luckcoffee.JPG"] forBarMetrics:UIBarMetricsDefault];
// 获取选中的TabBar
UINavigationController *navigationController = (UINavigationController *)self.parentViewController;
NSString *selectTab = navigationController.tabBarItem.title;
NSLog(@"选中的TabBar标题为:%@",selectTab);
}
3、UITabBarController
// push到下个界面隐藏底部TabBar
loginViewController.hidesBottomBarWhenPushed = YES;
// 获取当前选中的item
selectedItem
// badge的数值
tabBarItem.badgeValue = @"10";
// Tab标签栏跳转,比如从用户中心跳转到首页:
[self.navigationController popViewControllerAnimated:NO];
AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
UITabBarController *tab = (UITabBarController *)delegate.window.rootViewController;
tab.selectedIndex = 0;
// 数组
self.viewControllers = @[redVC, blueVC];
十、GestureRecognizer
1、Tap: 点击
2020-10-29 15:43:11.537921+0800 UIKitGrammarDemo[27813:955310] 点击改变testView的颜色
// Tap: 点击
- (void)tapGestureRecognizer
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapView:)];
tap.numberOfTapsRequired = 2;// 设置轻拍次数
tap.numberOfTouchesRequired = 2;// 设置手指字数
[self.gestureRecognizerView addGestureRecognizer:tap];
}
- (void)tapView:(UITapGestureRecognizer *)sender
{
// 改变testView的颜色
self.gestureRecognizerView.backgroundColor = [UIColor colorWithRed:arc4random()%256/255.0 green:arc4random()%256/255.0 blue:arc4random()%256/255.0 alpha:1];
NSLog(@"点击改变testView的颜色");
}
2、Swipe: 轻扫
2020-10-29 15:49:03.819006+0800 UIKitGrammarDemo[1244:183307] 轻扫改变testView的颜色
2020-10-29 15:49:09.874471+0800 UIKitGrammarDemo[1244:183307] 从左往右轻扫
- (void)swipeGestureRecognizer
{
UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeView:)];
swipe.numberOfTouchesRequired = 1;// 设置手指个数
swipe.direction = UISwipeGestureRecognizerDirectionLeft;// 设置轻扫方向(默认是从左往右)
[self.gestureRecognizerView addGestureRecognizer:swipe];
}
- (void)swipeView:(UISwipeGestureRecognizer *)sender
{
// 改变testView的颜色
self.gestureRecognizerView.backgroundColor = [UIColor colorWithRed:arc4random()%256/255.0 green:arc4random()%256/255.0 blue:arc4random()%256/255.0 alpha:1];
NSLog(@"轻扫改变testView的颜色");
if (sender.direction == UISwipeGestureRecognizerDirectionLeft)
{
NSLog(@"从左往右轻扫");
}
}
3、LongPress: 长按
2020-10-29 15:51:28.415827+0800 UIKitGrammarDemo[1248:184810] 长按改变testView的颜色
- (void)longPressGestureRecognizer
{
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
longPress.minimumPressDuration = 2;// 最小长按时间
[self.gestureRecognizerView addGestureRecognizer:longPress];
}
- (void)longPress:(UILongPressGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateBegan)// 在什么时候触发事件
{
// 改变testView的颜色
self.gestureRecognizerView.backgroundColor = [UIColor colorWithRed:arc4random()%256/255.0 green:arc4random()%256/255.0 blue:arc4random()%256/255.0 alpha:1];
NSLog(@"长按改变testView的颜色");
}
}
4、Pan: 平移
2020-10-29 16:35:39.932100+0800 UIKitGrammarDemo[28022:965824] 平移改变testView的颜色
- (void)panGestureRecognizer
{
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panView:)];
[self.gestureRecognizerView addGestureRecognizer:pan];
}
- (void)panView:(UIPanGestureRecognizer *)sender
{
// 起始点
CGPoint point = [sender translationInView:self.gestureRecognizerView];
// 第一种移动方法:每次移动都是从原来的位置移动
sender.view.transform = CGAffineTransformMakeTranslation(point.x, point.y);
// 第二种移动方式:以上次的位置为标准(第二次移动加上第一次移动量)
sender.view.transform = CGAffineTransformTranslate(sender.view.transform, point.x, point.y);
// 增量置为0
[sender setTranslation:CGPointZero inView:sender.view];
// 改变testView的颜色
self.gestureRecognizerView.backgroundColor = [UIColor colorWithRed:arc4random()%256/255.0 green:arc4random()%256/255.0 blue:arc4random()%256/255.0 alpha:1];
NSLog(@"平移改变testView的颜色");
}
5、ScreenEdgePan: 屏幕边缘平移
- (void)screenEdgePanGestureRecognizer
{
UIScreenEdgePanGestureRecognizer *screenEdgePan = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(screenEdgePanView:)];
screenEdgePan.edges = UIRectEdgeLeft;// 视图位置(屏幕边缘)
[self.gestureRecognizerView addGestureRecognizer:screenEdgePan];
}
// 不走这个方法......
- (void)screenEdgePanView:(UIScreenEdgePanGestureRecognizer *)sender
{
// 获取拖动的位置
CGPoint point = [sender translationInView:sender.view];
// 每次都以传入的translation为起始参照
sender.view.transform = CGAffineTransformTranslate(sender.view.transform, point.x, 0);
// 设置当前拖动的位置
[sender setTranslation:CGPointZero inView:sender.view];
// 改变testView的颜色
self.gestureRecognizerView.backgroundColor = [UIColor colorWithRed:arc4random()%256/255.0 green:arc4random()%256/255.0 blue:arc4random()%256/255.0 alpha:1];
if (sender.edges == UIRectEdgeLeft)
{
NSLog(@"从左边缘向右平移");
}
}
获取屏幕边缘扇动手势
- (UIScreenEdgePanGestureRecognizer *)screenEdgePanGestureRecognizer
{
UIScreenEdgePanGestureRecognizer *screenEdgePanGestureRecognizer = nil;
if (self.view.gestureRecognizers.count > 0)
{
for (UIGestureRecognizer *recognizer in self.view.gestureRecognizers)
{
NSLog(@"手势:%@",recognizer);
if ([recognizer isKindOfClass:[UIScreenEdgePanGestureRecognizer class]])
{
screenEdgePanGestureRecognizer = (UIScreenEdgePanGestureRecognizer *)recognizer;
break;
}
}
}
return screenEdgePanGestureRecognizer;
}
输出结果为:
2020-09-25 14:51:28.050270+0800 FunctionCodeBlockDemo[9250:18335987] 手势:<UIScreenEdgePanGestureRecognizer: 0x7fb58ce046d0; state = Possible; delaysTouchesBegan = YES; view = <UIView 0x7fb58f8068f0>; target= <(action=compare:, target=<LittleMethodViewController 0x7fb58cd06e70>)>>
6、Pinch: 捏合
- (void)pinchGestureRecognizer
{
// 设置缩放比例
self.lastScale = 1;
self.minScale = 0.5;
self.maxScale = 2;
UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchView:)];
[self.gestureRecognizerView addGestureRecognizer:pinch];
}
- (void)pinchView:(UIPinchGestureRecognizer *)recognizer
{
switch (recognizer.state)
{
case UIGestureRecognizerStateBegan:// 缩放开始
case UIGestureRecognizerStateChanged:// 缩放改变
{
CGFloat currentScale = [[self.gestureRecognizerView.layer valueForKeyPath:@"transform.scale"] floatValue];
CGFloat newScale = recognizer.scale - self.lastScale + 1;
newScale = MIN(newScale, self.maxScale / currentScale);
newScale = MAX(newScale, self.minScale / currentScale);
self.gestureRecognizerView.transform = CGAffineTransformScale(self.gestureRecognizerView.transform, newScale, newScale);
self.lastScale = recognizer.scale;
break;
}
case UIGestureRecognizerStateEnded:// 缩放结束
self.lastScale = 1;
break;
default:
break;
}
}
7、Rotation: 旋转
- (void)rotationGestureRecognizer
{
UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotationView:)];
[self.gestureRecognizerView addGestureRecognizer:rotation];
}
- (void)rotationView:(UIRotationGestureRecognizer *)sender
{
CGFloat rotationAngleInRadians = 0;// 旋转角度
// 手势识别完成,保存旋转的角度
if (sender.state == UIGestureRecognizerStateEnded)
{
rotationAngleInRadians += sender.rotation;
}
// 将上一次角度加上本次旋转的角度作为本次旋转的角度
self.view.transform = CGAffineTransformMakeRotation(rotationAngleInRadians + sender.rotation);
}
8、支持多个UIGestureRecongnizer共存
// 先接受到了手势事件,直接就处理而没有往下传递实际上就是两个手势共存的问题,先执行了UIScrollerView中包含的手势
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
// 滑动返回无法触发,说明UIScreenEdgePanGestureRecongnizer并没有接受到手势事件
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIScreenEdgePanGestureRecognizer class]])
{
// 返回YES,手势事件会一直往下传递,不论当前层次是否对该事件进行响应
return YES;
}
else
{
return NO;
}
}
9、响应屏幕触摸
// 手指按下时响应
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
NSLog(@"手指按下时响应");
}
// 手指移动时响应
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
NSLog(@"手指移动时响应");
}
// 手指抬起时响应
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
NSLog(@"手指抬起时响应");
}
// 触摸取消(意外中断, 如:电话, Home键退出等)
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];
NSLog(@"取消触摸响应(意外中断, 如:电话, Home键退出等)");
}
输出结果为:
2020-10-30 13:50:47.723917+0800 UIKitGrammarDemo[3009:597013] 手指按下时响应
2020-10-30 13:50:47.746602+0800 UIKitGrammarDemo[3009:597013] 手指移动时响应
2020-10-30 13:50:16.141409+0800 UIKitGrammarDemo[3009:597013] 手指抬起时响应
2020-10-30 13:50:47.747051+0800 UIKitGrammarDemo[3009:597013] 取消触摸响应(意外中断, 如:电话, Home键退出等)
10、运动事件监听
// 开始加速
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
[super motionBegan:motion withEvent:event];
NSLog(@"开始加速");
}
// 结束加速
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
[super motionEnded:motion withEvent:event];
NSLog(@"结束加速");
}
// 加速取消(意外中断, 如:电话, Home键退出等)
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
[super motionCancelled:motion withEvent:event];
NSLog(@"加速取消");
}
输出结果为:
2020-10-30 13:51:02.554064+0800 UIKitGrammarDemo[3009:597013] 开始加速
2020-10-30 13:51:03.149090+0800 UIKitGrammarDemo[3009:597013] 结束加速
11、手势谁先响应
a、Demo演示
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, 100, 100)];
btn.backgroundColor = UIColor.redColor;
[btn addTarget:self action:@selector(click) forControlEvents:UIControlEventTouchUpInside];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
[tap addTarget:self action:@selector(tap)];
[btn addGestureRecognizer:tap];
[self.view addSubview:btn];
- (void)click
{
NSLog(@"控件的点击事件");
}
- (void)tap
{
NSLog(@"手势");
}
输出结果为:
2020-07-21 17:59:15.797539+0800 Demo[72815:21154355] 手势
b、原因分析
当手指触碰到屏幕,无论是单点还是多点触碰,事件都会开始,直到用户所有的手指都离开屏幕。期间所有的UITouch
对象都被封装在UIEvent
事件对象中。因为UIEvent
包含了整个触碰过程中所有的触碰对象,所以可以调用allTouches
方法获取该事件内所有触碰对象。也可以调用touchesForView
或者 touchesForWindows
取出特定视图或者窗口上的触碰对象。
因为单击手势优先于UIView
的事件响应,如果手势识别成功,就会直接取消事件的响应链传递。如果手势识别失败了,触摸事件会继续走传递链,传递给响应链处理。但是手势识别是需要时间的,在possible
状态的时候,单击事件也可能已经传递给响应链了,如果手势识别器识别出触摸手势,会将传递给响应链的事件取消掉。
手势在触碰事件处理流程中,处于观察者的角色,其不是view
层级结构的一部分,所以不参与响应者链。在将触摸事件发送给hit-test view
之前,系统会先将触碰事件发送到view
绑定的Gesture Recognizer
上。
c、触碰冲突相关的属性
cancelsTouchesInView
为YES
时,表示当Gesture Recognizers
识别到手势后,会给hit-test view
发送touchesCancelled:
消息以取消hit-test view
对触碰序列的处理,这样只要Gesture Recognizer
响应此次触碰,响应者链的view
不再响应。如果为NO
,则不发送touchesCancelled:
消息,这样Gesture Recognizer
和view
同时响应触碰事件。默认值是YES
。
delaysTouchesBegan
为NO
时表示触碰序列已经开始而手势识别还未识别出此手势时,touch
事件会同时发给hit-test view
。为YES
时,延迟发送touchesEnded:
消息,手势失败时才发送。默认值是YES
。
userInteractionEnabled
默认是YES
,如果设置为NO
则不响应用户事件,并且把当前控件从事件队列中删除。也就是说设置了userInterfaceEnabled
属性为NO
的视图会打断响应者链导致该view
的subview
都无法响应事件。
multipleTouchEnabled
默认是NO
,如果设置为YES
则支持多点触碰。
exclusiveTouch
默认是NO
,如果设置为YES
则当前UIView
会独占整个Touch
事件。具体来说就是如果UIView
设置了exclusiveTouch
属性为YES
则当这个UIView
成为第一响应者时,在手指离开屏幕前其他view
不会响应任何touch
事件。比如UITableView
的每个cell
都需要使用exclusive
,否则同时点击多个cell
会触发每个视图的事件响应。手势识别会忽略此属性。
12、手势提供的属性和方法
手势状态
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
可以通过这个属性获取当前UIView的所有手势对象
NSArray *gestureRecognizers
添加手势
- (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer//增加一个手势
- (void)removeGestureRecognizer:(UIGestureRecognizer *)getureRecognizer//删除一个手势
- (BOOL)gestureRecognizerShouldBegan:(UIGestureRecognizer *)gestureRecognizer//询问是否开始执行该手势,默认返回YES
手势种类
UITabGestureRecognizer// 轻击手势
numberOfTapsRequired// 点击次数
numberOfTouchesRequired// 手指个数
UIPinchGestureRecognizer// 捏合手势
scale// 初始值为1,两手指距离减少则scale不断变小;两个手指重合则变为0
velocity// 初始值为0,手指移动的相对速度,两手指距离减少为负数,速度越快数值越少;两手指距离变大为整数,速度越快数值越大
UIRotationGestureRecognizer// 旋转手势
rotation// 初始值为0,两手指的旋转弧度,顺时针旋转为正数,逆时针旋转为负数
velocity// 初始值为0手指一动的相对速度,顺时针为正数越快值越大;逆时针为负越快越小
UISwipeGestureRecognizer// 轻扫手势
numberOfTouchesRequired// 手指个数
direction// 手势方向,如UISwipeGestureRecognizerDirectionRight向右
UIPanGestureRecognizer// 拖拽手势
mininumNumberOfTouches// 默认值为1,最少手指数量
maxnumNumberOfTouches// 最大手指数量
UILongPressGestrueRecognizer// 长按手势
numberOfTapsRequired// 默认值为0,轻击的次数
numberOfTouchesRequired// 默认值是1,手指数量
mininumPressDuration// 默认值为0.5,单位是秒
allowableMovement// 默认值为10,单位是像素pixels
调用的方法
- (id) initWithTarget:action:// 初始化方法
- (void)addTarget:action:
- (void)removeTarget:action:
手势识别当前所处状态
UIGestureRecognizerStatePossibel// 未识别状态
UIGestureRecognizerStateBegan// 手势开始
UIGestureRecognizerStateChanged// 手势改变
UIGestureRecognizerStateEnded// 手势结束
UIGestureRecognizerStateFailured // 手势失败,被其他事件中断。当把手势state设为这个值得时候相当于取消了这个手势
多手势兼容问题
[panRecognizer requireGestureRecognizerToFail:swipeRecognizer];// 捏合手势失败后才会触发拖拽手势。如果捏合手势成功则拖拽手势永远不会被触发
[rotationGestureRecognizer canBePreventedByGestureRecognizer:pinchGestureRecognizer];// 如果rotation手势重载了canBePreventedByGestureRecognizer方法并且返回YES。则旋转手势被捏合手势阻止
[rotationGestureRecognizer canPreventGestureRecognizer:pinchGestureRecognizer];// 如果rotation手势重载了canBePreventedByGestureRecognizer方法并且返回YES。则旋转手势阻止了捏合手势
UIGestureRecognizerDelegate
// 此方法在gesture recognizer视图传出UIGestureRecognizerStatePossible状态时调用,如果返回NO,则转换成UIGestureRecognizerStateFailed;如果返回YES,则继续识别。默认返回YES
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
// 此方法在window对象有触碰事件发生时,touchesBegan:withEvent:方法之前调用。如果返回NO,则GestureRecognizer忽略此触碰事件。默认返回YES。可以用于禁止某个区域的手势
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
// 如果有多个手势接收到了同一个消息,该回调方法决定当前手势是否要响应该事件,如果返回YES则该事件被响应,如果返回NO该事件将被忽略
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
Demo
Demo在我的Github上,欢迎下载。
BasicsDemo