一.
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导航栏不同