1. 能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?
不能向编译后得到的类中增加实例变量。
能向运行时创建的类中添加实例变量。
原因:
因为编译后的类已经注册在 runtime 中,类结构体中的 objc_ivar_list 实例变量的链表和 instance_size 实例变量的内存大小已经确定,同时 runtime 会调用 class_setIvarLayout 或 class_setWeakIvarLayout 来处理 strong weak 引用。所以不能向存在的类中添
加实例变量。
运行时创建的类是可以添加实例变量,调用 class_addIvar 函数。但是得在调用 objc_allocateClassPair 之后,
objc_registerClassPair 之前
2. 发送10个网络请求,然后再接收到所有回应之后执行后续操作,如何实现?
GCD信号量,队列组
做法:通过dispatch_group_t来实现,将每个请求放入到Group中,将合并成大图的操作放在dispatch_group_notify中实现。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{ /*加载图片1 / });
dispatch_group_async(group, queue, ^{ /加载图片2 / });
dispatch_group_async(group, queue, ^{ /加载图片3 */ });
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 合并图片
});
dispatch_group_enter()和dispatch_group_leave()
3. iOS数据本地存储方式?
1、沙盒
Document:适合存储重要的数据, iTunes同步应用时会同步该文件下的内容,(比如游戏中的存档)
Library/Caches:适合存储体积大,不需要备份的非重要数据,iTunes不会同步该文件
Library/Preferences:通常保存应用的设置信息, iTunes会同步
tmp:保存应用的临时文件,用完就删除,系统可能在应用没在运行时删除该目录下的文件,iTunes不会同步
// 获取Documents目录的路径
NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
// 得到Document目录下的fileName文件的路径
NSString *filePath = [documentPath stringByAppendingPathComponent:fileName];
//获取Library/Caches目录路径
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
//获取Library/Caches目录下的fileName文件路径
NSString *filePath = [path stringByAppendingPathComponent:fileName];
//获取temp路径
NSString *tmp = NSTemporaryDirectory();
//获取temp下fileName文件的路径
NSString *filePath = [tmp stringByAppendingPathComponent:fileName];
2、Plist
可以把字典或数组直接写入到文件中。另外,NSString、NSData、NSNumber等类型,也可以使用writeToFile:atomically:方法直接将对象写入文件中,只是Type为空。
// 要保存的数据
NSDictionary *dict = [NSDictionary dictionaryWithObject:@"iOS cookbook" forKey:@"bookName"];
// 获取路径.
NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
NSString *filePath = [documentPath stringByAppendingPathComponent:@"test.plist"];
// 写入数据
[dict writeToFile:filePath atomically:YES];
3、NSKeyedArchiver归档 / NSKeyedUnarchiver解档
如果想对一个自定义对象进行归档解档,首先要让对象遵守NSCoding协议。
其中:NSCoding协议有2个方法:
- (void)encodeWithCoder:(NSCoder *)aCoder
归档时调用这个方法,在方法中使用encodeObject:forKey:归档变量。
- (instancetype)initWithCoder:(NSCoder *)aDecoder
解档时调用这个方法,在方法中使用decodeObject:forKey读出变量。
//类方法,运用NSKeyedArchiver归档数据
+ (void)saveConfig:(DDAppConfigModel *)config
{
NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
NSString *path = [docPath stringByAppendingPathComponent:@"DDAppConfigModel.plist"];
[NSKeyedArchiver archiveRootObject:config toFile:path];
}
//类方法,使用NSKeyedUnarchiver解档数据
+ (DDAppConfigModel *)getConfig
{
NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
NSString *path=[docPath stringByAppendingPathComponent:@"DDAppConfigModel.plist"];
DDAppConfigModel *config = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
return config;
}
//类方法,运用NSKeyedArchiver归档数据
+ (void)saveConfig:(DDAppConfigModel *)config
{
NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
NSString *path = [docPath stringByAppendingPathComponent:@"DDAppConfigModel.plist"];
[NSKeyedArchiver archiveRootObject:config toFile:path];
}
//类方法,使用NSKeyedUnarchiver解档数据
+ (DDAppConfigModel *)getConfig
{
NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
NSString *path=[docPath stringByAppendingPathComponent:@"DDAppConfigModel.plist"];
DDAppConfigModel *config = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
return config;
}
4.NSUserDefaults
一般使用它来进行一些设置的记录,比如用户ID,开关是否打开等设置。通过键值对的方式记录设置。
NSUserDefaults可以存储的数据类型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。如果要存储其他类型,则需要转换为前面的类型,才能用NSUserDefaults存储。
存数据的方法:
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
NSString *name =@”default string“;
[defaults setObject:firstName forKey:@"name"];
[defaults synchronize];//用synchronize方法把数据持久化到standardUserDefaults数据库
去数据的方法:
//读取文件
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
NSString *name=[defaults objectForKey:@"name"];
NSInteger age=[defaults integerForKey:@"age"];
5、SQLite3
- (void)openDB{
//获取数据库文件路径
NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *fileName = [doc stringByAppendingPathComponent:@"students.sqlite"];
//将OC字符串转换为c语言的字符串
const char *cfileName = fileName.UTF8String;
//打开数据库文件(如果数据库文件不存在,那么该函数会自动创建数据库文件)
int result = sqlite3_open(cfileName, &_db);
if (result == SQLITE_OK) {//打开成功
NSLog(@"成功打开数据库");
}else{
NSLog(@"打开数据库失败");
}
}
- (void)createTable{
//创建表
const char *sql = "CREATE TABLE IF NOT EXISTS t_student(id integer PRIMARY KEY AUTOINCREMENT,name text NOT NULL,age integer NOT NULL);";
char *errmsg= NULL;
int result = sqlite3_exec(_db, sql, NULL, NULL, &errmsg);
if (result==SQLITE_OK) {
NSLog(@"创建表成功");
}else{
NSLog(@"创建表失败---%s",errmsg);
}
}
- (void)insertData{
//插入数据
for (int i=0; i<10; i++) {
//拼接sql语句
NSString *name = [NSString stringWithFormat:@"yixiangboy--%d",arc4random_uniform(100)];
int age = arc4random_uniform(20)+10;
NSString *sql = [NSString stringWithFormat:@"INSERT INTO t_student (name,age) VALUES ('%@',%d);",name,age];
//执行SQL语句
char *errmsg = NULL;
sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &errmsg);
if (errmsg) {//如果有错误信息
NSLog(@"插入数据失败--%s",errmsg);
}else{
NSLog(@"插入数据成功");
}
}
}
6、Core Data
7、FMDB
FMDB封装了SQLite的C语言API,更加面向对象。
FMDatabase:可以理解成一个数据库。
FMResultSet:查询的结果集合。
FMDatabaseQueue:运用多线程,可执行多个查询、更新。线程安全。
创建数据库 打开数据库
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"tmp.db"];
FMDatabase *db = [FMDatabase databaseWithPath:path];
if (![db open])
{ db = nil;
return;}
创建表
使用集合语句来进行表的创建
NSString *sql = @"create table bulktest1 (id integer primary key autoincrement, x text);"
"create table bulktest2 (id integer primary key autoincrement, y text);"
"create table bulktest3 (id integer primary key autoincrement, z text);"
"insert into bulktest1 (x) values ('XXX');"
"insert into bulktest2 (y) values ('YYY');"
"insert into bulktest3 (z) values ('ZZZ');";
success = [db executeStatements:sql];
查询
使用executeQuery 来执行查询语句,FMResultSet来进行存储查询的结果。
FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];
while ([s next]) {
//retrieve values for each record
}
更新
通过调用- (BOOL)executeUpdate:(NSString*)sql withParameterDictionary:(NSDictionary *)arguments执行插入、删除或者更新数据。
NSString *sql = ![rs next] ? INSERT_STATEMENT : UPDATE_STATEMENT;
BOOL success = [db executeUpdate:sql withParameterDictionary:[self pr_toDBDictionary]];
if (!success)
{
STLogDBLastError(db);
result = NO;
return;
}
多线程操作数据库:
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
[queue inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", @1];
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", @2];
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", @3];
FMResultSet *rs = [db executeQuery:@"select * from foo"];
while ([rs next]) {
…
}
}];
网友评论