一、导航控制器连线
从一个TableView控制器到View控制器
1)两个控制器要有对应的关联类
2)TableView的cell要设置id,保证在关联类里取到它,负责导航连线无效,因为压根就没取到它
3)用cell把View控制器push进来
4)再往TableView的导航条里拖左右item(注意:如果这个TableView是拖导航控制器自带的,那么只能拖右边的)
5)如果往TableView的导航条里拖左右item,同时设置它上一个的返回按钮;那么这个返回按钮将被它的左item覆盖掉
二、导航控制器结构的结论
1)根控制器只会加载一次,消失后,再显示不在加载
2)其余子控制器消失后,再显示将重新加载
三、导航控制器生命周期结论
1)是在各自的控制器里通过实现父类方法管理的
2)各控制器显示和消失的过程实质上是交替进行的
3)涉及的相关父类方法
// 控制器view加载完成的时候调用
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(@"viewDidLoad -- two");
}
// 控制器的view将要显示
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillDisappear:animated];
NSLog(@"viewWillAppear -- two");
}
// 控制器的view已经显示
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(@"viewDidAppear -- two");
}
// 控制器view将要消失
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
NSLog(@"viewWillDisappear -- two");
}
// 控制器view已经消失
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
NSLog(@"viewDidDisappear -- two");
}
四、改变pickerView大小 国旗选择项目
CGAffineTransform t0 = CGAffineTransformMakeTranslation(0, flag.bounds.size.height / 2);
CGAffineTransform s0 = CGAffineTransformMakeScale(1, 1);//变形范围
CGAffineTransform t1 = CGAffineTransformMakeTranslation(0, -flag.bounds.size.height / 2);
flag.transform = CGAffineTransformConcat(t0, CGAffineTransformConcat(s0, t1));
问题:CGAffineTransform 结构体的含义???
五、跳转页面 数据顺传原理 传到下一个控制器A–》B
1)时机:本控制器的控件的触发事件
2)原理:在目标控制器B里设置存储这个数据的属性变量,那么当在源控制器A创建目标控制器B对象的时候,把源控制器A的数据,存在这个变量里
那么,这时数据就会到达目标控制器B。关键:事先在B定义个接收变量
六、跳转页面 数据逆传原理 传到上一个控制器B–》A
1)时机:本控制器的控件的触发事件
2)原理:设置一个Block或代理
实现方法一:
用Block:
1)事先准备:在B定义一个带参无返回的Block
2)在A跳到B之前,A给B的Block一个实现方法C
3)B调回A之前,向它Block传参
4)跳转后,会自动执行方法C,A从方法C中得到B传的参数
用代理
1)事先准备:在定义一个代理协议和代理属性
2)在A设置代理并实现代理方法C
3)B调回A之前,用代理属性调用代理方法C
4)跳转后,会自动执行方法C,A从方法C中得到B传的参数
总结:
关键点:
1)是在A-》B之前创建的目标控制器B对象下手,因为在跳转到B之后,销毁B之前,B始终是这个B,里面的数据和方法始终会和A关联
2)准备使用在- (void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender 中完成
基于关键点:
B要做好事先准备
1)顺传:B要定义一个接收变量
2)逆传:定义一个Block或者定义代理变量
A对创建的B对象下手
1)顺传:赋值
2)逆传:Block实现并赋值;设置并实现代理
私人通讯录项目分析
1、功能分析
1)登录
2)添加
3)编辑
4)注销
5)显示
2.UI分析
2.1、登录界面
1)用户、密码输入框
2)记住密码、自动登录选择按钮
3)登录按钮 跳到显示界面
2.2、添加界面
1)界面标题 返回按钮
2)姓名、电话输入框
3)添加按钮
2.3.编辑界面
1)界面标题 编辑按钮 返回按钮
2)姓名、电话输入框
3)保存按钮
2.4.显示界面
1)销毁按钮、界面标题、添加按钮
2)跳到登录界面
3)跳到添加界面
4)跳到编辑界面
3.UI实现
4.代码实现
跳转传数据要重写这个方法
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
5.容易忘记的代码
1)延迟+加载效果
[SVProgressHUD showWithStatus:@"正在加载...." maskType:SVProgressHUDMaskTypeBlack];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
if ([name isEqualToString:@"1"]&&[password isEqualToString:@"1"]) {
//跳到联系人界面 login2contacts 是在面板上设置的
[self performSegueWithIdentifier:@"login2contacts" sender:nil];
}
else
{
[SVProgressHUD showErrorWithStatus:@"账号或密码不正确" maskType:SVProgressHUDMaskTypeBlack];
}
});
2)弹框创建 和 事件触发
// 注销按钮的点击事件
- (IBAction)logoutClick:(id)sender
{
UIActionSheet* sheet = [[UIActionSheet alloc] initWithTitle:@"你确定要离开我嘛" delegate:self cancelButtonTitle:@"不要" destructiveButtonTitle:@"我就是要离开你!!!" otherButtonTitles:nil, nil];
[sheet showInView:self.view];
}
- (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex)
return;
// 0.25
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// pop
[self.navigationController popViewControllerAnimated:YES];
});
}
3)判断代理是否实现和调用代理方法
if ([self.delegate respondsToSelector:@selector(editViewController:withContact:)]) {
[self.delegate editViewController:self withContact:self.contact];
}
4)定义Block(以下两种写法完全等同)
@property (nonatomic, copy) void (^editBlock)();
@property (nonatomic, copy) dispatch_block_t editBlock;
5)判断Block是否实现和调用Block
if (self.editBlock) {
self.editBlock();
}
6)手动跳转界面时 判断目标控制器的类别 做相应处理
[self performSegueWithIdentifier:@"login2contacts" sender:nil;
- (void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
// 获取目标控制器(UIViewController)
UIViewController* vc = segue.destinationViewController;
if ([vc isKindOfClass:[AddViewController class]]) {
// 获取目标控制器(强转成 addvc)
AddViewController* add = (AddViewController*)vc;
// 给目标控制器设置代理
add.delegate = self;
}
else {
EditViewController* edit = (EditViewController*)vc;
// 设置代理
// edit.delegate = self;
edit.editBlock = ^{
[self.tableView reloadData];
};
// 先获取到 点击的 indexpath
NSIndexPath* path = [self.tableView indexPathForSelectedRow];
// 通过indexpath 来 获取 需要传递的 对象
edit.contact = self.contacts[path.row];
}
}
7)获取TableView中选中Cell的索引
NSIndexPath* path = [self.tableView indexPathForSelectedRow];
8)文本框,开关控件都继承自UIControl 都可以addTarget 只对监听不同状态
// 监听文本框的内容的改变
[self.usernameField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
[self.passwordField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
// 监听开关的事件
[self.remPwdSwitch addTarget:self action:@selector(remPwdSwitchChange) forControlEvents:UIControlEventValueChanged];
[self.autoLoginSwitch addTarget:self action:@selector(autoLoginSwitchChange) forControlEvents:UIControlEventValueChanged];
9)可以选择view将要显示时,刷新数据
//- (void)viewWillAppear:(BOOL)animated
//{
//
// [super viewWillAppear:animated];
//
// // 刷新数据
// [self.tableView reloadData];
//}
10) 回到上一个页面
[self.navigationController popViewControllerAnimated:YES];
11) 从TaleViewController控制器加载cell://显示样式在面板设置下
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"contact"];
Person *person = self.persons[indexPath.row];
cell.textLabel.text = person.name;
//显示样式在面板设置下
cell.detailTextLabel.text = person.phoneNum;
return cell;
}
12)取消没有数据的分割线
self.tableView.tableFooterView = [[UIView alloc] init] ;