1. 能否向編譯后得到的類(lèi)中增加實(shí)例變量?能否向運(yùn)行時(shí)創(chuàng)建的類(lèi)中添加實(shí)例變量悼嫉?為什么诽俯?
不能向編譯后得到的類(lèi)中增加實(shí)例變量。
能向運(yùn)行時(shí)創(chuàng)建的類(lèi)中添加實(shí)例變量承粤。
原因:
因?yàn)榫幾g后的類(lèi)已經(jīng)注冊(cè)在 runtime 中暴区,類(lèi)結(jié)構(gòu)體中的 objc_ivar_list 實(shí)例變量的鏈表和 instance_size 實(shí)例變量的內(nèi)存大小已經(jīng)確定,同時(shí) runtime 會(huì)調(diào)用 class_setIvarLayout 或 class_setWeakIvarLayout 來(lái)處理 strong weak 引用辛臊。所以不能向存在的類(lèi)中添
加實(shí)例變量仙粱。
運(yùn)行時(shí)創(chuàng)建的類(lèi)是可以添加實(shí)例變量,調(diào)用 class_addIvar 函數(shù)彻舰。但是得在調(diào)用 objc_allocateClassPair 之后伐割,
objc_registerClassPair 之前
2.?發(fā)送10個(gè)網(wǎng)絡(luò)請(qǐng)求候味,然后再接收到所有回應(yīng)之后執(zhí)行后續(xù)操作,如何實(shí)現(xiàn)隔心?
GCD信號(hào)量白群,隊(duì)列組
做法:通過(guò)dispatch_group_t來(lái)實(shí)現(xiàn),將每個(gè)請(qǐng)求放入到Group中硬霍,將合并成大圖的操作放在dispatch_group_notify中實(shí)現(xiàn)帜慢。
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數(shù)據(jù)本地存儲(chǔ)方式唯卖?
1粱玲、沙盒
Document:適合存儲(chǔ)重要的數(shù)據(jù), iTunes同步應(yīng)用時(shí)會(huì)同步該文件下的內(nèi)容,(比如游戲中的存檔)
Library/Caches:適合存儲(chǔ)體積大拜轨,不需要備份的非重要數(shù)據(jù)抽减,iTunes不會(huì)同步該文件
Library/Preferences:通常保存應(yīng)用的設(shè)置信息, iTunes會(huì)同步
tmp:保存應(yīng)用的臨時(shí)文件,用完就刪除橄碾,系統(tǒng)可能在應(yīng)用沒(méi)在運(yùn)行時(shí)刪除該目錄下的文件卵沉,iTunes不會(huì)同步
// 獲取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
可以把字典或數(shù)組直接寫(xiě)入到文件中法牲。另外史汗,NSString、NSData皆串、NSNumber等類(lèi)型淹办,也可以使用writeToFile:atomically:方法直接將對(duì)象寫(xiě)入文件中,只是Type為空恶复。
// 要保存的數(shù)據(jù)
NSDictionary *dict = [NSDictionary dictionaryWithObject:@"iOS cookbook" forKey:@"bookName"];
// 獲取路徑.
NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
NSString *filePath = [documentPath stringByAppendingPathComponent:@"test.plist"];
// 寫(xiě)入數(shù)據(jù)
[dict writeToFile:filePath atomically:YES];
3怜森、NSKeyedArchiver歸檔 / NSKeyedUnarchiver解檔
如果想對(duì)一個(gè)自定義對(duì)象進(jìn)行歸檔解檔,首先要讓對(duì)象遵守NSCoding協(xié)議谤牡。
其中:NSCoding協(xié)議有2個(gè)方法:
- (void)encodeWithCoder:(NSCoder *)aCoder
歸檔時(shí)調(diào)用這個(gè)方法副硅,在方法中使用encodeObject:forKey:歸檔變量。
- (instancetype)initWithCoder:(NSCoder *)aDecoder
解檔時(shí)調(diào)用這個(gè)方法翅萤,在方法中使用decodeObject:forKey讀出變量恐疲。
//類(lèi)方法,運(yùn)用NSKeyedArchiver歸檔數(shù)據(jù)
+ (void)saveConfig:(DDAppConfigModel *)config
{
? ? NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
? ? NSString *path = [docPath stringByAppendingPathComponent:@"DDAppConfigModel.plist"];
? ? [NSKeyedArchiver archiveRootObject:config toFile:path];
}
//類(lèi)方法套么,使用NSKeyedUnarchiver解檔數(shù)據(jù)
+ (DDAppConfigModel *)getConfig
{
? ? NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
? ? NSString *path=[docPath stringByAppendingPathComponent:@"DDAppConfigModel.plist"];
? ? DDAppConfigModel *config = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
? ? return config;
}
//類(lèi)方法培己,運(yùn)用NSKeyedArchiver歸檔數(shù)據(jù)
+ (void)saveConfig:(DDAppConfigModel *)config
{
? ? NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
? ? NSString *path = [docPath stringByAppendingPathComponent:@"DDAppConfigModel.plist"];
? ? [NSKeyedArchiver archiveRootObject:config toFile:path];
}
//類(lèi)方法,使用NSKeyedUnarchiver解檔數(shù)據(jù)
+ (DDAppConfigModel *)getConfig
{
? ? NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
? ? NSString *path=[docPath stringByAppendingPathComponent:@"DDAppConfigModel.plist"];
? ? DDAppConfigModel *config = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
? ? return config;
}
4.NSUserDefaults
一般使用它來(lái)進(jìn)行一些設(shè)置的記錄胚泌,比如用戶(hù)ID省咨,開(kāi)關(guān)是否打開(kāi)等設(shè)置。通過(guò)鍵值對(duì)的方式記錄設(shè)置玷室。
NSUserDefaults可以存儲(chǔ)的數(shù)據(jù)類(lèi)型包括:NSData零蓉、NSString笤受、NSNumber、NSDate敌蜂、NSArray箩兽、NSDictionary。如果要存儲(chǔ)其他類(lèi)型章喉,則需要轉(zhuǎn)換為前面的類(lèi)型汗贫,才能用NSUserDefaults存儲(chǔ)。
存數(shù)據(jù)的方法:
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
NSString *name =@”default string“;
[defaults setObject:firstName forKey:@"name"];
[defaults synchronize];//用synchronize方法把數(shù)據(jù)持久化到standardUserDefaults數(shù)據(jù)庫(kù)
去數(shù)據(jù)的方法:
//讀取文件
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
NSString *name=[defaults objectForKey:@"name"];
NSInteger age=[defaults integerForKey:@"age"];
5囊陡、SQLite3
- (void)openDB{
? ? //獲取數(shù)據(jù)庫(kù)文件路徑
? ? NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
? ? NSString *fileName = [doc stringByAppendingPathComponent:@"students.sqlite"];
? ? //將OC字符串轉(zhuǎn)換為c語(yǔ)言的字符串
? ? const char *cfileName = fileName.UTF8String;
? ? //打開(kāi)數(shù)據(jù)庫(kù)文件(如果數(shù)據(jù)庫(kù)文件不存在芳绩,那么該函數(shù)會(huì)自動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)文件)
? ? int result = sqlite3_open(cfileName, &_db);
? ? if (result == SQLITE_OK) {//打開(kāi)成功
? ? ? ? NSLog(@"成功打開(kāi)數(shù)據(jù)庫(kù)");
? ? }else{
? ? ? ? NSLog(@"打開(kāi)數(shù)據(jù)庫(kù)失敗");
? ? }
}
- (void)createTable{
? ? //創(chuàng)建表
? ? 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(@"創(chuàng)建表成功");
? ? }else{
? ? ? ? NSLog(@"創(chuàng)建表失敗---%s",errmsg);
? ? }
}
- (void)insertData{
? ? //插入數(shù)據(jù)
? ? for (int i=0; i<10; i++) {
? ? ? ? //拼接sql語(yǔ)句
? ? ? ? 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];
? ? ? ? //執(zhí)行SQL語(yǔ)句
? ? ? ? char *errmsg = NULL;
? ? ? ? sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &errmsg);
? ? ? ? if (errmsg) {//如果有錯(cuò)誤信息
? ? ? ? ? ? NSLog(@"插入數(shù)據(jù)失敗--%s",errmsg);
? ? ? ? }else{
? ? ? ? ? ? NSLog(@"插入數(shù)據(jù)成功");
? ? ? ? }
? ? }
}
6掀亥、Core Data?
7撞反、FMDB
FMDB封裝了SQLite的C語(yǔ)言API,更加面向?qū)ο蟆?/p>
FMDatabase:可以理解成一個(gè)數(shù)據(jù)庫(kù)搪花。
FMResultSet:查詢(xún)的結(jié)果集合遏片。
FMDatabaseQueue:運(yùn)用多線(xiàn)程,可執(zhí)行多個(gè)查詢(xún)撮竿、更新吮便。線(xiàn)程安全。
創(chuàng)建數(shù)據(jù)庫(kù) 打開(kāi)數(shù)據(jù)庫(kù)
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"tmp.db"];
FMDatabase *db = [FMDatabase databaseWithPath:path];
if (![db open])
{? ? db = nil;
? ? return;}
創(chuàng)建表
使用集合語(yǔ)句來(lái)進(jìn)行表的創(chuàng)建
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];
查詢(xún)
使用executeQuery 來(lái)執(zhí)行查詢(xún)語(yǔ)句幢踏,F(xiàn)MResultSet來(lái)進(jìn)行存儲(chǔ)查詢(xún)的結(jié)果髓需。
FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];
while ([s next]) {
? ? //retrieve values for each record
}
更新
通過(guò)調(diào)用- (BOOL)executeUpdate:(NSString*)sql withParameterDictionary:(NSDictionary *)arguments執(zhí)行插入、刪除或者更新數(shù)據(jù)房蝉。
NSString *sql = ![rs next] ? INSERT_STATEMENT : UPDATE_STATEMENT;
BOOL success = [db executeUpdate:sql withParameterDictionary:[self pr_toDBDictionary]];
if (!success)
{
? ? STLogDBLastError(db);
? ? result = NO;
? ? return;
}
多線(xiàn)程操作數(shù)據(jù)庫(kù):
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]) {
? ? ? ? …
? ? }
}];