sqlite에서 nsdata로 일부 이미지를 캐싱하려고하는데 sqlite3_exec 및 원시 SQL 문자열을 사용하여 바이트 배열을 삽입하려고하면 문제가 발생합니다 (NSString으로)Object-c에서 sqlite3_exec을 사용하여 BLOB로 UIImage를 삽입하는 방법
NSData *imgData = UIImagePNGRepresentation(img);
NSString* sql = [NSString stringWithFormat:@"INSERT INTO persistedimg (imgx,idvalx) VALUES (%@,'%@')", imgData, idValue];
rc = sqlite3_exec(db, [sql UTF8String], callbackFunction, (void*)contextObject, &zErrMsg);
위의 문제는 바이트 대신 SQL 문자열에 NSData를 직접 추가하는 것입니다.
나는이... [imgData bytes], [imgData length]
같은 것을하고 싶어하지만 방법과 같은 전형적인 "_bind_blob"를 사용하지 않는 때문에 원시 문자열 승/그것을 할 방법을 잘 모르겠어요
나는 이미지 삽입을 지원하기 위해 승 스틱/단순히 새로운 방법을 쓰고 싶은 래퍼를 사용하고 업데이트
/쿼리
명령아래 내 전체 래퍼 클래스가 지금까지
**
#import "SQLiteAccess.h"
#import <sqlite3.h>
@implementation SQLiteAccess
+ (NSString *)pathToDB {
NSString *dbName = @"test123";
NSString *originalDBPath = [[NSBundle mainBundle] pathForResource:dbName ofType:@"db"];
NSString *path = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *appSupportDir = [paths objectAtIndex:0];
NSString *dbNameDir = [NSString stringWithFormat:@"%@/test123", appSupportDir];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDir = NO;
BOOL dirExists = [fileManager fileExistsAtPath:dbNameDir isDirectory:&isDir];
NSString *dbPath = [NSString stringWithFormat:@"%@/%@.db", dbNameDir, dbName];
if(dirExists && isDir) {
BOOL dbExists = [fileManager fileExistsAtPath:dbPath];
if(!dbExists) {
NSError *error = nil;
BOOL success = [fileManager copyItemAtPath:originalDBPath toPath:dbPath error:&error];
if(!success) {
NSLog(@"error = %@", error);
} else {
path = dbPath;
}
} else {
path = dbPath;
}
} else if(!dirExists) {
NSError *error = nil;
BOOL success =[fileManager createDirectoryAtPath:dbNameDir attributes:nil];
if(!success) {
NSLog(@"failed to create dir");
}
success = [fileManager copyItemAtPath:originalDBPath toPath:dbPath error:&error];
if(!success) {
NSLog(@"error = %@", error);
} else {
path = dbPath;
}
}
return path;
}
+ (NSNumber *)executeSQL:(NSString *)sql withCallback:(void *)callbackFunction context:(id)contextObject {
NSString *path = [self pathToDB];
sqlite3 *db = NULL;
int rc = SQLITE_OK;
NSInteger lastRowId = 0;
rc = sqlite3_open([path UTF8String], &db);
if(SQLITE_OK != rc) {
NSLog(@"Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return nil;
} else {
char *zErrMsg = NULL;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
rc = sqlite3_exec(db, [sql UTF8String], callbackFunction, (void*)contextObject, &zErrMsg);
if(SQLITE_OK != rc) {
NSLog(@"Can't run query '%@' error message: %s\n", sql, sqlite3_errmsg(db));
sqlite3_free(zErrMsg);
}
lastRowId = sqlite3_last_insert_rowid(db);
sqlite3_close(db);
[pool release];
}
NSNumber *lastInsertRowId = nil;
if(0 != lastRowId) {
lastInsertRowId = [NSNumber numberWithInteger:lastRowId];
}
return lastInsertRowId;
}
static int singleRowCallback(void *queryValuesVP, int columnCount, char **values, char **columnNames) {
NSMutableDictionary *queryValues = (NSMutableDictionary *)queryValuesVP;
int i;
for(i=0; i<columnCount; i++) {
[queryValues setObject:values[i] ? [NSString stringWithFormat:@"%s",values[i]] : [NSNull null]
forKey:[NSString stringWithFormat:@"%s", columnNames[i]]];
}
return 0;
}
+ (NSString *)selectOneValueSQL:(NSString *)sql {
NSMutableDictionary *queryValues = [NSMutableDictionary dictionary];
[self executeSQL:sql withCallback:singleRowCallback context:queryValues];
NSString *value = nil;
if([queryValues count] == 1) {
value = [[queryValues objectEnumerator] nextObject];
}
return value;
}
+ (NSNumber *)insertWithSQL:(NSString *)sql {
sql = [NSString stringWithFormat:@"BEGIN TRANSACTION; %@; COMMIT TRANSACTION;", sql];
return [self executeSQL:sql withCallback:NULL context:NULL];
}
+ (void)updateWithSQL:(NSString *)sql {
sql = [NSString stringWithFormat:@"BEGIN TRANSACTION; %@; COMMIT TRANSACTION;", sql];
[self executeSQL:sql withCallback:NULL context:nil];
}
@end
입니다 **
이 솔루션에 어떤 도움이 큰 것!
나는 현상금을 거절했으나 개인적으로 필요한 경우 2 주 동안 두 가지 현상금을 지급하는 것이 더 나은 결과를 얻을 것이라고 생각합니다. –