下面是我在林达iOS基于iOS 4的培训课程中学到的一个代码片段。
我打算在我的Xcode 4.2中实现相同的代码,Xcode 4.2是用iOS 5 SDK打开的。它给了我一个错误:
错误:语义问题:将“__strong id *”发送到'__unsafe_unretained id **‘类型的参数,更改保留/释放指针的属性“
- (NSNumber *) insertRow:(NSDictionary *) record {
// NSLog(@"%s", __FUNCTION__);
int dictSize = [record count];
// the values array is used as the argument list for bindSQL
id keys[dictSize]; // not used, just a side-effect of getObjects:andKeys
id values[dictSize];
[record getObjects:values andKeys:keys]; // convenient for the C array
// construct the query
NSMutableArray * placeHoldersArray = [NSMutableArray arrayWithCapacity:dictSize];
for (int i = 0; i < dictSize; i++) // array of ? markers for placeholders in query
[placeHoldersArray addObject: [NSString stringWithString:@"?"]];
NSString * query = [NSString stringWithFormat:@"insert into %@ (%@) values (%@)",
tableName,
[[record allKeys] componentsJoinedByString:@","],
[placeHoldersArray componentsJoinedByString:@","]];
[self bindSQL:[query UTF8String] arguments:(va_list)values];
sqlite3_step(statement);
if(sqlite3_finalize(statement) == SQLITE_OK) {
return [self lastInsertId];
} else {
NSLog(@"doQuery: sqlite3_finalize failed (%s)", sqlite3_errmsg(database));
return [NSNumber numberWithInt:0];
}
}**实际情况是整个功能的以下部分。
int dictSize = [record count];
// the values array is used as the argument list for bindSQL
id keys[dictSize]; // not used, just a side-effect of getObjects:andKeys
id values[dictSize];
[record getObjects:values andKeys:keys]; // convenient for the C array我怎么解决这个问题?
发布于 2012-12-02 07:13:46
这个功能有很多问题。编译器错误的修正是使用keys所有权限定符声明__unsafe_unretained和__unsafe_unretained:
__unsafe_unretained id keys[dictSize]; // not used, just a side-effect of getObjects:andKeys
__unsafe_unretained id values[dictSize];但是,强制转换(va_list)values是未定义的行为。不要这样做。
由于您根本没有使用keys数组,所以最好这样做:
- (NSNumber *) insertRow:(NSDictionary *) record {
int count = [record count];
NSMutableArray * placeHoldersArray = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count; i++) {
[placeHoldersArray addObject: @"?"];
}
NSString * query = [NSString stringWithFormat:@"insert into %@ (%@) values (%@)",
tableName,
[[record allKeys] componentsJoinedByString:@","],
[placeHoldersArray componentsJoinedByString:@","]];
[self bindSQL:[query UTF8String] arguments:[record allValues]];
sqlite3_step(statement);
if(sqlite3_finalize(statement) == SQLITE_OK) {
return [self lastInsertId];
} else {
NSLog(@"doQuery: sqlite3_finalize failed (%s)", sqlite3_errmsg(database));
return [NSNumber numberWithInt:0];
}
}然后修改bindSQL:arguments:以接受NSArray *而不是va_list。如果需要帮助,请向我们展示bindSQL:arguments:的源代码。
(但是,我不认为allKeys和allValues返回并行数组(…)是有记载的。)
发布于 2012-12-02 07:15:27
为const char指针编辑:
- (NSNumber *) insertRow:(NSDictionary *) record {
NSArray * placeHoldersArray = [NSArray array];
const char * cStrings[record.count];
NSArray * keys = [record allKeys];
NSUInteger i=0;
for (id key in keys) {
id object = [record objectForKey:key];
if ([object isKindOfClass:[NSString class]])
cStrings[i++] = [(NSString*)object UTF8String];
else
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Expected NSString" userInfo:nil];
placeHoldersArray = [placeHoldersArray arrayByAddingObject: @"?"];
}
NSString * query = [NSString stringWithFormat:@"insert into %@ (%@) values (%@)",
tableName,
[keys componentsJoinedByString:@","],
[placeHoldersArray componentsJoinedByString:@","]];
[self bindSQL:[query UTF8String] arguments:(va_list)cStrings];
sqlite3_step(statement);
if(sqlite3_finalize(statement) == SQLITE_OK) {
return [self lastInsertId];
} else {
NSLog(@"doQuery: sqlite3_finalize failed (%s)", sqlite3_errmsg(database));
return [NSNumber numberWithInt:0];
}
}在update方法中,您应该理解va_list只是一组任意数量的参数。假定被调用的方法知道如何确定类型。这方面的一个例子是NSLog。它使用格式字符串来确定未知数量的变量的类型,这些变量作为va_list传入,即逗号分隔的值。因为你只有一个值,就把这个值传递给你。我还不清楚sqlite是否需要c字符串,或者在这种情况下它是否需要一个整数。
https://stackoverflow.com/questions/13666986
复制相似问题