标签:
动画
[UIView beginAnimations:nil context:nil];
设置动画时间
[UIView s ! etAnimationDuration:3];
[UIView setAnimationDelegate:self];
只要写在开始和结束之间的代码, 就会被执行动画
但是: 并不是所有的代码都能够执行动画
只有属性声明中说明了是animatable的属性,才可以执行UIView动画
CGRect tempFrame2 = self.hudLabel.frame;
tempFrame2.origin.y -= 100;
self.hudLabel.frame = tempFrame2;
self.hudLabel.alpha = 1.0;
self.hudLabel.hidden = YES;
动画结束
[UIView commitAnimations];
2.block式动画 Duration: 动画执行的时长 animations: 在block中写需要执行动画的代码 completion: 动画结束后系统会自动调用该block delay: 延迟多少秒
[UIView animateWithDuration:2 animations:^{
self.hudLabel.alpha = 1.0;
}];
[UIView animateWithDuration:1.0 animations:^{
self.hudLabel.alpha = 1.0;
} completion:^(BOOL finished) {
NSLog(@"动画结束了");
[UIView animateWithDuration:1.0 delay:1.0 options:kNilOptions animations:^{
self.hudLabel.alpha = 0.0;
} completion:nil];
}];
// 1.创建一个AlertController
// Title : 按钮上显示的文字
// style: 按钮的样式
// handler: 点击按钮之后的回调
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];
// 2.显示
[self presentViewController:alertVc animated:YES completion:nil];
// 添加一个输入框
[alertVc addTextFieldWithConfigurationHandler:^(UITextField * __nonnull textField) {
textField.text = @"用户名";
NSLog(@"textField");
}];
UIActionSheet
// 1.创建UIActionSheet
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"哥是标题" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"确定" otherButtonTitles:@"其它", @"Other", nil];
// 2.显示UIActionSheet
[sheet showInView:self.view];
// 只要UIActionSheet上的按钮被点击就会调用
// actionSheet:谁触发事件就会把谁传递进来
// clickedButtonAtIndex:当前被点击按钮的索引
-(void)actionSheet:(nonnull UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSLog(@"%ld", buttonIndex);
}
UIAlertView
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"哥是标题" message:@"姐是正文..." delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
alert.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
[alert show];
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonInde
{
// 取消 = 0, 确定 = 1 , 其他 = 2 , Other = 3 以此类推
switch (buttonInde)
{
case 0:
NSLog(@"点击了取消");
break;
case 1:
NSLog(@"点击了确定");
break;
case 2:
NSLog(@"点击了其他");
break;
case 3:
NSLog(@"点击了Other");
break;
default:
break;
}
}
代理的应用场景
A对象向监听B对象的变化, A对象就可以成为B对象的代理 B对象发生一些变化想通知A对象, 那么A对象就可以成为B对象的代理
监听
自定义HUD
// 1.创建父控件
UIView *cover = [[UIView alloc] init];
cover.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
cover.frame = CGRectMake(0, 0, 150, 150);
cover.center = self.view.center;
// 修改父控件为圆角
cover.layer.cornerRadius = 10;
[self.view addSubview:cover];
// 2.创建菊花
// 菊花有默认的尺寸
// 注意: 虽然有默认的尺寸, 但是要想显示必须让菊花转起来
UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
activity.center = CGPointMake(cover.frame.size.width * 0.5, 50);
[activity startAnimating];
[cover addSubview:activity];
// 3.创建UILabel
UILabel *label = [[UILabel alloc] init];
// label.backgroundColor = [UIColor purpleColor];
label.textAlignment = NSTextAlignmentCenter;
label.text = @"正在拼命加载中...";
label.frame = CGRectMake(0, cover.frame.size.height - 80, cover.frame.size.width, 80);
[cover addSubview:label];
自定义按钮
这是不可以的
XMGButton *btn = [[XMGButton alloc] init];
btn.imageView.frame = CGRectMake(0, 0, btn.frame.size.width, btn.frame.size.width);
需要在自定义按钮类实现中重写如下方法才可以修改UIButton内部的子控件的frame
该方法用于返回按钮内部的图片的尺寸和位置
-(CGRect)imageRectForContentRect:(CGRect)contentRect
{
// x = 0, y = 0, width = 父控件的宽度, height = 父控件的宽度
return CGRectMake(0, 0, contentRect.size.width, contentRect.size.width);;
}
-(CGRect)titleRectForContentRect:(CGRect)contentRect
{
// x = 0, y = 父控件的宽度 width = 父控件的宽度, height = 父控件的高度 - 父控件的宽度
return CGRectMake(0, contentRect.size.width, contentRect.size.width, contentRect.size.height - contentRect.size.width);
}
UIButton内边距
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setImage:[UIImage imageNamed:@"024"] forState:UIControlStateNormal];
[btn setTitle:@"贵宾" forState:UIControlStateNormal];
btn.frame = CGRectMake(100, 100, 145, 60);
// 上左下右
// 如果是设置contentEdgeInsets, 会把UIImageView和UIlabel当做一个整体移动
// 如果是设置titleEdgeInsets/imageEdgeInsets. 那么不会影响到另外一个, 也就是只会改变当前设置的这个控件
btn.contentEdgeInsets = UIEdgeInsetsMake(20, 0, 0, 0);
btn.titleEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0);
btn.imageEdgeInsets = UIEdgeInsetsMake(50, 0, 0, 00);
[self.view addSubview:btn];
图片拉伸
UIButton *btn = [[UIButton alloc] init];
UIImage *image = [UIImage imageNamed:@""];
// 1.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];
*/
// 2.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];
*/
// 3.iOS6开始
/*
// resizingMode指定拉伸模式
// 平铺
// 拉伸
UIEdgeInsets insets = UIEdgeInsetsMake(5, 5, 5, 5);
UIImage *newImage = [image resizableImageWithCapInsets:insets resizingMode:UIImageResizingModeStretch];
*/
[btn setBackgroundImage:newImage forState:UIControlStateNormal];
btn.frame = CGRectMake(100, 100, 200, 80);
[self.view addSubview:btn];
Person *p = [Person new];
p.name = @"lmj";
p.money = 998;
#pragma mark 获取单个值
NSString *name =[p valueForKey:@"name"];
NSLog(@"name = %@",name);
double money =[[p valueForKey:@"money"] doubleValue];
NSLog(@"money = %f", money);
#pragma mark 获取多层值
NSString *dogName = [p valueForKey:@"dog.name"];
NSString *dogName = [p valueForKeyPath:@"dog.name"];
NSLog(@"dogName = %@", dogName);
#pragma mark 模型转字典
NSDictionary *dict = [p dictionaryWithValuesForKeys:@[@"name", @"money"]];
NSLog(@"%@", dict);
#pragma mark 获取数组中对象的值
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"];
NSLog(@"res = %@", res);
#pragma mark 运算符
id res1 = [arr valueForKeyPath:@"@avg.money"];
NSLog(@"res = %@", res1);
}
- (void)kvcSetter
{
Person *p = [[Person alloc] init];
// p.name = @"lnj"; // setter
// p.money = 998.0;
#pragma mark 单个值
/*
// KVC == KEY VALUE CODING
// Value : 值, 只能传对象
// forKey: 需要给谁(哪个属性)赋值
// setValue:forKey:方法, 只能给对象的直接属性赋值
[p setValue:@"lmj" forKey:@"name"];
// @(998.0) == [NSNumber numberWithDouble:(double)]
[p setValue:@(668.0) forKey:@"money"];
*/
#pragma mark 多层赋值
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"];
*/
#pragma mark 给私有成员变量赋值
/*
// [p setValue:@"lnj" forKey:@"_name"];
// [p setValue:@(30) forKey:@"_age"];
// SEL sel = @selector(say);
// [p performSelector:sel];
// [p say];
*/
#pragma mark 字典转模型
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];
NSLog(@"p.dog = %@", p.dog);
NSLog(@"name = %@, money = %f", p.name, p.money
// KVO == Key Value Observing
// 作用: 可以监听某个对象属性的改变
Person *p = [Person new];
p.name = @"lnj";
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_Person
*/
p->_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);
}
标签:
原文地址:http://www.cnblogs.com/liujiaoxian/p/4697057.html