UIButton
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
千万不要这样写:
btn.titleLabel.text = @"我是按钮";
- 一般情况下给按钮设置内容都是setXXX
- [btn setTitle:@"我是按钮"
forState:UIControlStateNormal];
- [btn setTitle:@"哥是高亮"
forState:UIControlStateHighlighted];
2.设置标题颜色
objc btn.backgroundColor = [UIColor redColor]; [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
设置图标
objc [btn setImage:[UIImage imageNamed:@"common_icon_check"] forState:UIControlStateNormal];
设置背景图片
objc [btn setBackgroundImage:[UIImage imageNamed:@"common_button_big_blue_highlighted"] forState:UIControlStateDisabled];
监听按钮的点击
Target:让谁监听按钮 action:监听到之后需要执行的方法 Events:事件的类型
- 规律:
只要是继承于UIControl的控件, 都可以通过addTarget来添加监听
objc [btn addTarget:self action:@selector(customBtnClick) forControlEvents:UIControlEventTouchUpInside];
---UISwitch sw = nil;
objc [sw addTarget:<#(nullable id)#> action:<#(nonnull SEL)#> forControlEvents:<#(UIControlEvents)#>]
UISegmentedControl *sc = nil;
objc [sc addTarget:<#(nullable id)#> action:<#(nonnull SEL)#> forControlEvents:<#(UIControlEvents)#>]
UITextField *tf = nil;
objc [tf addTarget:<#(nullable id)#> action:<#(nonnull SEL)#> forControlEvents:<#(UIControlEvents)#>]
设置字体
btn.titleLabel.font = [UIFont systemFontOfSize:30];
设置frame
objc btn.frame = CGRectMake(100, 100, 100, 100);
[self.view addSubview:btn];
UIButton图片拉伸
iOS5以前
- LeftCapWidth: 左边多少不能拉伸
- 右边多少不能拉伸 = 控件的宽度 - 左边多少不能拉伸 - 1
- right = width - leftCapWidth - 1
- 1 = width - leftCapWidth - right
- topCapHeight: 顶部多少不能拉伸
- 底部有多少不能拉伸 = 控件的高度 - 顶部多少不能拉伸 - 1
- bottom = height - topCapWidth - 1
1 = height - topCapWidth - bottom
UIImage *newImage = [image stretchableImageWithLeftCapWidth:5 topCapHeight:5];
iOS5开始
- UIEdgeInsets是告诉系统哪些地方需要受保护, 也就是不可以拉伸
- resizableImageWithCapInsets默认拉伸方式是平铺
UIEdgeInsets insets = UIEdgeInsetsMake(image.size.height * 0.5, image.size.width * 0.5, image.size.height * 0.5, image.size.width * 0.5);
- UIImage *newImage = [image resizableImageWithCapInsets:insets];
iOS6开始
- resizingMode指定拉伸模式
- 平铺
拉伸
UIEdgeInsets insets = UIEdgeInsetsMake(5, 5, 5, 5);
```objc
UIImage *newImage = [image resizableImageWithCapInsets:insets resizingMode:UIImageResizingModeStretch];
```
currentTitle和btn.titlelabel.text 区别
UIButton *btn = [UIButtonbuttonWithType:UIButtonTypeCustom];
1、[btn setTitle:@"测试一下" forState:UIControlStateNormal];输出:CurrentTitleLabel:测试一下,currentTitle:测试一下。模拟器button上显示:测试一下2、btn.titlelabel.text = @"测试一下";输出:CurrentTitleLabel:测试一下,currentTitle:(null)。模拟器button上无显示3、[btn setTitle:@"测试一下" forState:UIControlStateNormal];btn.titlelabel.text = @"测试二下";输出:CurrentTitleLabel:测试二下,currentTitle:测试一下。模拟器button上显示:测试二下4、btn.titlelabel.text = @"测试二下";[btn setTitle:@"测试一下" forState:UIControlStateNormal];输出:CurrentTitleLabel:测试一下,currentTitle:测试一下。模拟器button上显示:测试一下currentTitle 和titlelabel 不一样。按钮上显示的是CurrnetTitle,而不是titlelabel。
KVC
Person *p = [Person new];
p.name = @"lmj";
p.money = 998;
p.dog = [Dog new];
p.dog.name = @"wangcai";
p.dog.price = 110;
获取单个值
NSString *name = [p valueForKey:@"name"];
double money = [[p valueForKey:@"money"] doubleValue];
获取多层值
NSString *dogName = [p valueForKey:@"dog.name"];
NSString *dogName = [p valueForKeyPath:@"dog.name"];
模型转字典
NSDictionary *dict = [p dictionaryWithValuesForKeys:@[@"name", @"money"]];
获取数组中对象的值
Person *p1 = [Person new];p1.name = @"zs";p1.money = 111;Person *p2 = [Person new];p2.name = @"ls";p2.money = 222;Person *p3 = [Person new];p3.name = @"ww";p3.money = 666;NSArray *arr = @[p1, p2, p3];
- 如果数组中的元素都是同一种类型的数据, 可以使用KVC获取数组中所有对象的某个属性的值
NSArray *res = [arr valueForKeyPath:@"name"];
运算符
id res1 = [arr valueForKeyPath:@"@avg.money"];
单个值
- KVC == KEY VALUE CODING
- Value : 值, 只能传对象
- forKey: 需要给谁(哪个属性)赋值
- setValue:forKey:方法, 只能给对象的直接属性赋值
- [p setValue:@"lmj" forKey:@"name"];
- @(998.0) == [NSNumber numberWithDouble:(double)]
- [p setValue:@(668.0) forKey:@"money"];
多层赋值
p.dog = [Dog new];
p.dog.name == [[p dog] setName:]
p.dog.name = @"wangwang";
p.dog.price = 110.0;
setValue:forKeyPath: 可以给对象的间接属性赋值. 多层赋值
- 建议: 以后在开发中都使用
setValue:forKeyPath:
[p setValue:@"xiaoqiang" forKeyPath:@"dog.name"];
- 建议: 以后在开发中都使用
[p setValue:@(110) forKeyPath:@"dog.price"];
给私有成员变量赋值
[p setValue:@" ydz " forKey:@"_name"];
[p setValue:@(30) forKey:@"_age"];
用sel可以调用私有方法
SEL sel = @selector(say);
[p performSelector:sel];
[p say];
字典转模型
NSDictionary *dict = @{ @"name":@"xxx", @"money": @(998.1), @"score":@(100) @"dog":@{ @"name":@"wangcai", @"price":@(110) } }; p.name = dict[@"name"]; p.money = [dict[@"money"] doubleValue];
注意点:
- 1.如果想使用KVC进行字典转模型, 那么字典中的key必须和模型中的属性一模一样(个数 + 名称)``` this class is not key value coding-compliant for the key score.'```
- 2.如果使用KVC进行字典转模型, 只能对当前调用KVC方法的对象进行转换, 不能对它的属性的对象进行转换
setValuesForKeysWithDictionary:方法内部的实现原理
1.会拿到字典中的key, 然后根据这个key取出字典中的值, 然后再根据这个key赋值给对象
[p setValue:@"xxx" forKey:@"name"];
[p setValuesForKeysWithDictionary:dict];
KVO
KVO == Key Value Observing
作用: 可以监听某个对象属性的改变
Person *p = [Person new]; p.name = @"ydz"; p.age = 30;
- 第一个参数: 告诉系统哪个对象监听
- 第二个参数: 监听当前对象的哪个属性
- 第三个参数: 监听到属性改变之后, 传递什么值
第四个参数: 需要传递的参数 (这个参数不是传递给属性的)
给p这个对象添加一个监听 , 监听p对象的age属性的改变, 只要age属性改变就通知self
[p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
p.age = 50;
NSLog(@"-------------------");
p.age = 100;
- 注意: 如果使用KVO监听某个对象的属性, 当对象释放之前一定要移除监听
reason: 'An instance 0x7f9483516610 of class Person was deallocated while key value observers were still registered with it.
注意: KVO只能监听通过set方法修改的值
KVO的原理:
只要给一个对象注册一个监听, 那么在运行时, 系统就会自动给该对象生成一个子类对象, 并且重写自动生成的子类对象的被监听属性的set方法, 然后在set方法中通知监听者 NSKVONotifying_Personp->_age = 998;
从p对象上移除self对它的age属性的监听
[p removeObserver:self forKeyPath:@"age"];
- 只要监听到属性的改变就会调用
- keyPath: 被监听的属性名称
- object : 被监听的对象
context: 注册监听的时候传入的值
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary *)change context: (nullable void *)context { NSLog(@"keyPath = %@, object = %@ , change = %@, context = %@", keyPath, object, change, context); }
提示框(HUD)
1.创建一个AlertController
- (void)touchesBegan:(nonnull NSSet*)touches withEvent:(nullable UIEvent *)event{ UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:@"标题" message:@"正文" preferredStyle:UIAlertControllerStyleActionSheet];UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * __nonnull action) { NSLog(@"点击了确定");}];UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * __nonnull action) { NSLog(@"点击了取消");}];[alertVc addAction:action1];[alertVc addAction:action2];注意: 如果UIAlertController的样式是ActionSheet, 就不能添加输入框 reason: 'Text fields can only be added to an alert controller of style UIAlertControllerStyleAlert'[alertVc addTextFieldWithConfigurationHandler:^(UITextField * __nonnull textField) { }];2.显示[self presentViewController:alertVc animated:YES completion:nil];
}
====
1.创建alert控制器
- (void)useAlertControllerAlert{UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:@"哥是标题" message:@"姐是正文..." preferredStyle:UIAlertControllerStyleAlert];// 2.添加一个按钮// Title : 按钮上显示的文字// style: 按钮的样式// handler: 点击按钮之后的回调UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * __nonnull action) { NSLog(@"点击了确定按钮");}];UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * __nonnull action) { NSLog(@"点击了取消按钮");}];[alertVc addAction:action1];[alertVc addAction:action2];// 3.添加一个输入框[alertVc addTextFieldWithConfigurationHandler:^(UITextField * __nonnull textField) { textField.text = @"用户名"; NSLog(@"textField");}];[alertVc addTextFieldWithConfigurationHandler:^(UITextField * __nonnull textField) { textField.secureTextEntry = YES; NSLog(@"textField");}];[alertVc addTextFieldWithConfigurationHandler:^(UITextField * __nonnull textField) { NSLog(@"textField");}];// 4.presentViewController弹出一个控制器[self presentViewController:alertVc animated:YES completion:nil];
}
===
1.创建UIActionSheet
- (void)useActionSheet{// 2.UIActionSheet//UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"哥是标题" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"确定" otherButtonTitles:@"其它", @"Other", nil];// 2.显示UIActionSheet[sheet showInView:self.view];}
UIActionSheetDelegate
- 只要UIActionSheet上的按钮被点击就会调用
- actionSheet:谁触发事件就会把谁传递进来
clickedButtonAtIndex:当前被点击按钮的索引
- (void)actionSheet:(nonnull UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { NSLog(@"%ld", buttonIndex); }
===
1.UIAlerView
- 如果看到iOS提供的方法中有... 就代表是一个可变参数
可以传一个或者多个
代理的应用场景:
A对象向监听B对象的变化, A对象就可以成为B对象的代理 B对象发生一些变化想通知A对象, 那么A对象就可以成为B对象的代理 监听 规律: 1.以后但凡看到iOS中需要传递对象成为某个对象的代理, 那么直接写上某个对象的类名 + Delegate即可 2.一般情况下, 代理中的方法都是以控件的名称去掉前缀开头 例如: 要成为UIAlertView的代理 , 写上 UIAlertViewDelegate - (void)useAlert { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"哥是标题" message:@"姐是正文..." delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil]; alert.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput; }
UIAlertViewDelegate
- 只要UIAlertView上的按钮被点击, 就会调用
- alertView:谁触发事件就会把谁传递进来
- ButtonAtIndex: 当前被点击按钮的索引
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonInde