如果数组是线程安全的,那么这个函数有什么问题?

时间:2011-09-23 13:07:16

标签: ios4 iphone-sdk-3.0 thread-safety nsmutablearray nsmutabledictionary

我完全迷失了我的代码所发生的事情。这让我想到了&使用Array的线程安全概念清楚。是NSMutableArray还是NSM​​utableDictionary线程安全吗?

虽然我的代码正在执行,但是MainArray的值得到了更改,尽管已经添加到Array中。

请尝试执行此代码,在您的系统上非常容易。我无法摆脱此陷阱。

它是返回Array的函数。 我要做的是: - (数组)(主阵列) - >(词典),键值(主阵列中的多个词典) ----->上面的字典中有9个数组。

这是我为Array.But开发的结构,甚至在

之前
#define TILE_ROWS    3
#define TILE_COLUMNS 3
#define TILE_COUNT   (TILE_ROWS * TILE_COLUMNS)

-(NSArray *)FillDataInArray:(int)counter
{

    NSMutableArray *temprecord = [[NSMutableArray alloc] init];
    for(int i = 0; i <counter;i++)
    {

        if([temprecord count]<=TILE_COUNT)
        {
            NSMutableDictionary *d1 = [[NSMutableDictionary alloc]init];
            [d1 setValue:[NSString stringWithFormat:@"%d/2011",i+1] forKey:@"serial_data"];
            [d1 setValue:@"Friday 13 Sep 12:00 AM" forKey:@"date_data"];
            [d1 setValue:@"Description Details  " forKey:@"details_data"];
            [d1 setValue:@"Subject Line" forKey:@"subject_data"];   
            [temprecord addObject:d1];
            d1= nil;
            [d1 release];

            if([temprecord count]==TILE_COUNT)
            {
                NSMutableDictionary *holderKey = [[NSMutableDictionary alloc]initWithObjectsAndKeys:temprecord,[NSString stringWithFormat:@"%d",[casesListArray count]+1],nil];
                [self.casesListArray addObject:holderKey];
                [holderKey release];
                holderKey =nil;
                [temprecord removeAllObjects];              
            }
        }
        else {
            [temprecord removeAllObjects];
            NSMutableDictionary *d1 = [[NSMutableDictionary alloc]init];
            [d1 setValue:[NSString stringWithFormat:@"%d/2011",i+1] forKey:@"serial_data"];
            [d1 setValue:@"Friday 13 Sep 12:00 AM" forKey:@"date_data"];
            [d1 setValue:@"Description Details  " forKey:@"details_data"];
            [d1 setValue:@"Subject Line" forKey:@"subject_data"];   
            [temprecord addObject:d1];
            d1= nil;
            [d1 release];
        }

    }

    return temprecord;
    [temprecord release];
}

此代码有什么问题?每次在Array中有9条记录时,它只是替换整个Array值而不是仅替换特定的键值。

1 个答案:

答案 0 :(得分:1)

首先,Cocoa不可变集合是线程安全的。他们的可变对应物线程安全。使代码线程安全取决于应用程序的设计。多线程程序中的一个好习惯是使用尽可能多的不可变数据。

其次,在:

NSMutableDictionary *holderKey = [[NSMutableDictionary alloc]initWithObjectsAndKeys:temprecord,[NSString stringWithFormat:@"%d",[casesListArray count]+1],nil];
[self.casesListArray addObject:holderKey];
[holderKey release];
holderKey =nil;
[temprecord removeAllObjects]; 

您有以下内容:

  • temprecord指向一个可变数组
  • 您创建了一个名为holderKey的可变字典,其中包含一个对象,即与上面相同的temprecord
  • 您将此可变字典添加到self.casesListArray
  • 您发布holderKey,因为它已在上一步中添加到数组中而未被解除分配
  • 您从temprecord删除所有对象。由于temprecordholderKey中的数组相同,因此它也是该字典中的空数组。由于holderKey被添加到self.casesListArray,因此相应的数组元素是相同的字典,具有相同的(现在为空)数组。

由于在执行该方法期间将-removeAllObjects发送到temprecord,您可能希望存储数组当前值的副本(可变或不可变):

NSMutableArray *tempRecordCopy = [temprecord mutableCopy];

NSMutableDictionary *holderKey = [[NSMutableDictionary alloc]initWithObjectsAndKeys:tempRecordCopy,[NSString stringWithFormat:@"%d",[casesListArray count]+1],nil];

[tempRecordCopy release];

我不确定你是否需要数组是否可变。如果不这样做,请将其更改为NSArray-copy,并且您将拥有不可变副本。

最后,您使用的是奇怪的模式,导致托管内存设置中的内存泄漏。例如,在:

d1= nil;
[d1 release];

由于您将nil分配给d1,因此以下指令[d1 release]实际上是无操作。这意味着d1不再指向原始对象,并且此对象尚未释放。不要这样做。代替:

[d1 release];

在大多数情况下已经足够了,如果你真的需要nil变量,请在发布后执行:

[d1 release];
d1 = nil;

修改:进一步说明:在:

return temprecord;
[temprecord release];

temprecord未被释放,因为该方法在返回时结束。释放temprecord的尝试是无法访问的代码,永远不会被执行。你想要这个:

return [temprecord autorelease];

另一个编辑:请注意,-setObject:forKey:是将对象添加到字典的规范方法。您正在使用-setValue:forKey:,这是一种KVC方法,在字典上使用时具有特殊的行为。除非您熟悉KVC,否则我建议您使用-setObject:forKey: