总结一下今天遇到的几个问题:
一、关于NSBundle
NSBundle里的文件都是readonly,不可修改,我在NSBundle里读取一个sqlite文件,然后用sql语句更新数据库,发现数据并没有保存
NSString *dataPath = [[NSbundle mainBundle] pathForResources:@"data" ofType:@"sqlite"];
以这为路径打开的数据库是不可更改的。
解决方法:把sqlite文件先拷贝到用户目录下
苹果官方建议的目录是Document目录,因此依照以下代码进行拷贝
NSString *beginPath = [[NSBundle mainBundle] pathForResource:@"data2" ofType:@"sqlite"];
NSString *targetPath = [NSSearchPathForDictionariesInDomains(NSDocumentDicrectory, NSUserDomainMask, YES) objectAtIndex:0];
//注意以下这个语句NSSearchPathForDictionariesInDomains(NSDocumentDicrectory, NSUserDomainMask, YES)的第一个参数,如果第一个参数一不小心写成NSDocumentationDicrectory,也会发生一系列的错误,比如无法创建文件等。 暂时不知道为什么
NSString *targetFile = [targetPath stringByAppendingPathComponent:@"data2.sqlite"];
NSFileManager *fm = [NSFileManager defaultManager];
if (![fm fileExistsAtPath:targetFile]){
NSError *error;
[fm copyItemAtPath:beginPath toPath:targetFile error:&error]; // 注意第二个参数一定要是以文件名结尾的路径,而不能是目录路径,否则会出错“this operation cann't be completed”
}
sqlite3_open([targetFile UTF8String], &database);
二、内存管理问题
之前程序的占用内存随着程序的使用时间而增加,肯定是哪里有内存泄漏了,检查发现sqlite3_step执行后忘了sqlite3_finalize,这会导致严重的内存泄漏,切记
三、模拟器运行正常,真机却不行
我有一个这样的类:HLOptionContent,用于存储一个选项的内容
@interface HLOptionContent : NSObject
@property (weak nonatomic) NSString *kara;
@property (weak, nonatomic) NSString *japaneseWord;
- (id)initWithKara:(NSString *)kara japaneseWord:(NSString *)japaneseWord;
@end
我在初始化选项的时候这样写到
//查询其他3个日文(只检索japansesWord)
self.arrayOfJapaneseWord = [[NSMutableArray alloc] init];
const char *query = "select japanese_word,kana from word_tbl where word_id <> ? order by random() limit 3";
sqlite3_stmt *queryStmt;
int result = sqlite3_prepare_v2(wordDatabase, query, -1, &queryStmt, nil);
if (result == SQLITE_OK) {
sqlite3_bind_int(queryStmt, 1, self.wordID);
while (sqlite3_step(queryStmt) == SQLITE_ROW) {
NSString *aJapaneseWord = [NSString stringWithCString:(const char *)sqlite3_column_text(queryStmt, 0) encoding:NSUTF8StringEncoding];
NSString *aKara = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(queryStmt, 1)];
HLOptionContent *aOption = [[HLOptionContent alloc] initWithKara:aKara japaneseWord:aJapaneseWord];
[self.arrayOfJapaneseWord addObject:aOption]; //MARK
}
}
sqlite3_finalize(queryStmt);
HLOptionContent *aOption = [[HLOptionContent alloc] initWithKara:self.pronunceKara japaneseWord:self.japaneseWord];
[self.arrayOfJapaneseWord addObject:aOption];//把当前待背单词的日文也加进来
这段代码在模拟器上完全正常,4个选项可以在View中正常显示,而在真机中却不行。在上面的MARK处插了个断点开始调试,在真机中发现当aOption被加入self.arrayOfjapaneseWord后,它的kara和japaneseWord都是nil。想想也应该是这样,因为这两个属性都是weak。然后我把HLOptionContent的两个属性都改成strong后,运行正常。但奇怪的是,属性是weak的时候,在模拟器中插断点调试发现这两个属性的值并不为空!!!