首页 > 代码库 > IOS学习笔记 -- Segue、数据存储、UITabBarController

IOS学习笔记 -- Segue、数据存储、UITabBarController

一. Segue
1.Storyboard上每一根用来界面跳转的线,都是一个UIStoryboardSegue对象(简称Segue)
每一个Segue对象,都有3个属性
1>.唯一标识: @property (nonatomic, readonly) NSString *identifier;
2>.来源控制器: @property (nonatomic, readonly) id sourceViewController;
3>.目标控制器: @property (nonatomic, readonly) id destinationViewController;

2.根据Segue的执行(跳转)时刻,Segue可以分为2大类型
1>.自动型:点击某个控件后(比如按钮),自动执行Segue,自动完成界面跳转; 如果点击某个控件后,不需要做任何判断,一定要跳转到下一个界面,建议使用“自动型Segue”
2>.手动型:需要通过写代码手动执行Segue,才能完成界面跳转; 如果点击某个控件后,需要做一些判断,也就是说:满足一定条件后才跳转到下一个界面,建议使用“手动型Segue”
[self performSegueWithIdentifier:@"唯一标识" sender:nil];
3>.无论手动型的Segue,还是自动线的Segue跳转前都会执行
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;

3.控制器之间的数据传递主要有2种情况:顺传和逆传
1>.顺传:
控制器的跳转方向: A -> C;数据的传递方向: A -> C
数据的传递方式: 在A的prepareForSegue:sender:方法中根据segue参数取得destinationViewController, 也就是控制器C, 直接给控制器C传递数据
2>.逆传:
控制器的跳转方向: A -> C;数据的传递方向: C -> A
数据的传递方式: 让A成为C的代理, 在C中调用A的代理方法,通过代理方法的参数传递数据给A

二.数据存储
iOS应用数据存储的常用方式
1>.XML属性列表(plist)归档
2>.Preference(偏好设置)
3>.NSKeyedArchiver归档(NSCoding)
4>.SQLite3
4>.Core Data

1.应用沙盒
1>.每个iOS应用都有自己的应用沙盒,IOS8以前应用不能访问其他应用的沙盒
2>.应用沙盒的文件系统目录
a. 应用程序包:包含了所有的资源文件和可执行文件
b. Documents:保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录。
c. tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录
d. Library/Caches:保存应用运行时生成的需要持久化的数据,iTunes同步设备时不会备份该目录。一般存储体积大、不需要备份的非重要数据
e. Library/Preference:保存应用的所有偏好设置,iOS的Settings(设置)应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录
3>.获取目录:
沙盒根目录:NSString *home = NSHomeDirectory();
获取Documents目录
NSString *documents = [home stringByAppendingPathComponent:@"Documents"];
NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];// 建议
获取tmp目录
NSString *tmp = NSTemporaryDirectory();
获取Library/Caches目录‘
NSString *caches = [[home stringByAppendingPathComponent:@"Library"] stringByAppendingPathComponent:@"caches"];
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];// 建议
获取Library/Preference目录
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

2.XML属性列表(plist)归档
1>.获取Documents目录并生成文件
// 动态获取Documents目录
NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 拼接文件路径
NSString *path = [doc stringByAppendingPathComponent:@"abc.plist"];
2>.数据写入文件
NSDictionary *dict = @{@"name": @"jack", @"age":@"28"};
// 调用writeToFile将数据写入文件
[dict writeToFile:path atomically:YES];
3>.读取数据
// 读取数据
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSLog(@"%@", dict);
4>.使用注意
plist只能储存系统自带的一些常规的类,也就是有writeToFile方法的对象才可以使用plist保存数据
如:NSString/NSArray/NSDictionary/NSData/NSNumber...

3.Preference(偏好设置)
1>.偏好设置是专门用来保存应用程序的配置信息的, 一般情况不要再偏好设置中保存其他数据,如果利用系统的偏好设置来存储数据, 默认就是存储在Preferences文件夹下面的,偏好设置会将所有的数据保存到(Library/Preference下)同一个文件中
// 获取NSUserDefaults对象
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
2>.保存数据
// 保存数据(如果设置数据之后没有同步, 会在将来某一时间点自动将数据保存到Preferences文件夹下面)
[defaults setObject:@"jack" forKey:@"name"];
[defaults setInteger:13 forKey:@"age"];
[defaults setDouble:1.80 forKey:@"height"];
// 让NSUserDefaults立刻保存数据
[defaults synchronize];
3>.读取数据
// 通过NSUserDefaults获取保存的数据
NSString *name = [defaults objectForKey:@"name"];
int age = [defaults integerForKey:@"age"];
NSLog(@"%@", name);
NSLog(@"%d", age);

4.NSKeyedArchiver归档(NSCoding)
1>.常规的类可以直接用NSKeyedArchiver进行归档和恢复, 自定义的对象需要遵守NSCoding协议才可以用NSKeyedArchiver进行归档和恢复
2>.NSCoding协议有2个方法:
encodeWithCoder: 每次归档对象时,都会调用这个方法。一般在这个方法里面指定如何归档对象中的每个实例变量,可以使用encodeObject:forKey:方法归档实例变量
initWithCoder: 每次从文件中恢复(解码)对象时,都会调用这个方法。一般在这个方法里面指定如何解码文件中的数据为对象的实例变量,可以使用decodeObject:forKey方法解码实例变量
// 如果想将一个自定义对象保存到文件中必须实现NSCoding协议
@interface NJPerson : NSObject <NSCoding>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) double height;
@end
@implementation NJPerson
// 当将一个自定义对象保存到文件的时候就会调用该方法
// 在该方法中说明如何存储自定义对象的属性
// 也就说在该方法中说清楚存储自定义对象的哪些属性
- (void)encodeWithCoder:(NSCoder *)encoder
{
// [super encodeWithCoder:aCoder]; 如果父类遵守了NSCoding协议,需要添加这个
[encoder encodeObject:self.name forKey:@"name"];
[encoder encodeInteger:self.age forKey:@"age"];
[encoder encodeFloat:self.height forKey:@"heigth"];
}
// 当从文件中读取一个对象的时候就会调用该方法
// 在该方法中说明如何读取保存在文件中的对象
// 也就是说在该方法中说清楚怎么读取文件中的对象
- (id)initWithCoder:(NSCoder *)decoder
{
// if (self = [super initWithCoder:aDecoder]) { 如果父类遵守了NSCoding协议,需要替换成这个
if (self = [super init]) {
self.name = [decoder decodeObjectForKey:@"name"];
self.age = [decoder decodeIntegerForKey:@"age"];
self.height = [decoder decodeFloatForKey:@"heigth"];
}
return self;
}
3>.获取Documents目录并生成文件
// 动态获取Documents目录
NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 拼接文件路径
NSString *path = [doc stringByAppendingPathComponent:@"abc.arc"];
4>.数据写入文件
// 创建对象
NJPerson *p = [[NJPerson alloc] init];
p.name = @"jack";
p.age = 28;
p.height = 1.76;
[NSKeyedArchiver archiveRootObject:p toFile:path];
5>.读取数据
NJPerson *p = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
NSLog(@"%@ %d %.1f", p.name, p.age, p.height);

三.UITabBarController
跟UINavigationController类似,UITabBarController也可以轻松地管理多个控制器,轻松完成控制器之间的切换,典型例子就是QQ、微信等应用
1.UITabBarController的使用步骤
初始化UITabBarController
设置UIWindow的rootViewController为UITabBarController
根据具体情况,通过addChildViewController方法添加对应个数的子控制器

2.UITabBarController添加控制器的方式有2种
1>.添加单个子控制器: - (void)addChildViewController:(UIViewController *)childController;
2>.设置子控制器数组: @property(nonatomic,copy) NSArray *viewControllers;

3.UITabBar UITabBarController有多少个子控制器,那么UITabBar内部就会有多少个UITabBarButton作为子控件
UITabBarButton里面显示什么内容,由对应子控制器的tabBarItem属性决定,UITabBarItem有以下属性影响着UITabBarButton的内容
1>.标题文字: @property(nonatomic,copy) NSString *title;
2>.图标: @property(nonatomic,retain) UIImage *image;
3>.选中时的图标: @property(nonatomic,retain) UIImage *selectedImage;
4>.提醒数字: @property(nonatomic,copy) NSString *badgeValue;

4. App主流UI框架结构
UIWindow -> UITabBarController -> UINavigationController -> UIViewController
UINavigationController和UITabBarController互换的话,那所有的UIViewController的导航栏就会只有一个,无法修改不同的UIView导航栏不同