- 动画
- 1.头尾式动画 动画开始
[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.头尾式动画 动画开始
- UIAlertController HUD(提示框)
- 继承UIViewController
- 注意:
- 如果UIAlertController的样式是ActionSheet, 就不能添加输入框
// 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];
- 如果UIAlertController的样式是UIAlertControllerStyleAlert 就可以添加输入框
// 添加一个输入框 [alertVc addTextFieldWithConfigurationHandler:^(UITextField * __nonnull textField) { textField.text = @"用户名"; NSLog(@"textField"); }];
- 如果UIAlertController的样式是UIAlertControllerStyleAlert 就可以添加输入框
- 如果UIAlertController的样式是ActionSheet, 就不能添加输入框
- 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];
- 只要UIAlertView上的按钮被点击, 就会调用 alertView:谁触发事件就会把谁传递进来 ButtonAtIndex: 当前被点击按钮的索引
-(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对象的代理
- 监听
- 规律:
- 1.以后但凡看到iOS中需要传递对象成为某个对象的代理, 那么直接写上某个对象的类名 + Delegate即可
- 2.一般情况下, 代理中的方法都是以控件的名称去掉前缀开头
- 规律:
- 自定义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];
- 自定义按钮
- 注意: 不能在外界直接修改UIButton内部的子控件的frame
这是不可以的 XMGButton *btn = [[XMGButton alloc] init]; btn.imageView.frame = CGRectMake(0, 0, btn.frame.size.width, btn.frame.size.width);
- 需要在自定义按钮类实现中重写如下方法才可以修改UIButton内部的子控件的frame
- 该方法用于返回按钮内部标题的尺寸和位置
- 该方法是由系统自动调用的
- 系统每次调用该方法, 都会将父控件的frame传递进来
- contentRect: 父控件的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内部的子控件的frame还可以用-(void)layoutSubviews方法实现
- 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内部的子控件的frame
- 图片拉伸
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];
- KVC
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
// 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);
}
时间: 2024-10-12 13:39:45