首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将__string发送到__unsafe_unretained更改保留/释放指针的属性

将__string发送到__unsafe_unretained更改保留/释放指针的属性
EN

Stack Overflow用户
提问于 2012-12-02 06:30:24
回答 2查看 1.2K关注 0票数 0

下面是我在林达iOS基于iOS 4的培训课程中学到的一个代码片段。

我打算在我的Xcode 4.2中实现相同的代码,Xcode 4.2是用iOS 5 SDK打开的。它给了我一个错误:

错误:语义问题:将“__strong id *”发送到'__unsafe_unretained id **‘类型的参数,更改保留/释放指针的属性“

代码语言:javascript
复制
- (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];
    }
}

**实际情况是整个功能的以下部分。

代码语言:javascript
复制
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

我怎么解决这个问题?

EN

回答 2

Stack Overflow用户

发布于 2012-12-02 07:13:46

这个功能有很多问题。编译器错误的修正是使用keys所有权限定符声明__unsafe_unretained__unsafe_unretained

代码语言:javascript
复制
__unsafe_unretained id keys[dictSize];  // not used, just a side-effect of getObjects:andKeys
__unsafe_unretained id values[dictSize];

但是,强制转换(va_list)values是未定义的行为。不要这样做。

由于您根本没有使用keys数组,所以最好这样做:

代码语言:javascript
复制
- (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:的源代码。

(但是,我不认为allKeysallValues返回并行数组(…)是有记载的。)

票数 0
EN

Stack Overflow用户

发布于 2012-12-02 07:15:27

为const char指针编辑:

代码语言:javascript
复制
- (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字符串,或者在这种情况下它是否需要一个整数。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13666986

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档