【问题标题】:Items disappearing from array within array从数组中的数组中消失的项目
【发布时间】:2013-08-22 15:12:58
【问题描述】:

我创建了一个 NSMutableArray,只要我的应用程序存在,我就将它称为 suseranArray,就在我的主类的 @implementation 之后。该数组将包含一个名为 Vassal 的类的多个对象。封臣就是:

1) 一个 NSMutableString 2) 另一个 NSMutableString 3) 一个 NSMutableArray 4) 另一个 NSMutable 数组

创建的每个 Vassal 在应用的生命周期中也是必需的,而且它们永远不会改变。

这些对象在 .h 文件中作为(保留)属性,在 .m 文件中合成,并且每当在 init 函数期间创建对象 Vassal 时,每个对象都会被赋予一个 alloc+init。每个附庸都有数据填充并存储在宗主数组中。第 3 项总是有几个元素,出现 bug 后,我放一行检查它是否为空,但从来没有,生活是美好的。

现在,稍后当需要某个 Vassal 对象时,我们尝试访问其第三个属性以获取其中的数据,有时该数组为空...我检查它是否以某种方式消失了,但它总是在调试中,带有一个像 0x2319f8a0 这样的好地址,这是有道理的,因为它上面的 NSMutableString 位于地址 0x2319fb40 - (经过很多头痛后,我期待 00000000)。怎么了?我的脑袋,我正在创建一个 RETAINed 对象,它保留默认放入的数据,并且该对象被放入另一个对象中,但不知何故数组内的数据消失了。什么可能的情况会导致这种情况?谢谢你的时间:)

注意:在这个开发阶段,最后一个数组目前只保存一项,奇怪的是,尽管这两个数组是“兄弟”,但永远不会丢失一项。

Vassal.h
@interface Vassal : NSObject
@property  (retain) NSMutableString *wordBody;
@property  (retain) NSMutableString *wordCode;
@property   (retain) NSMutableArray *wordRelations;
@property   (retain) NSMutableArray *wordLinks;
@end

Vassal.m
@implementation Vassal:NSObject
@synthesize wordBody;
@synthesize wordCode;
@synthesize wordRelations;
@synthesize wordLinks;
-(NSObject*) init
{
    if(self=[super init])
    {
        wordBody=[[NSMutableString alloc] init];
        wordCode=[[NSMutableString alloc] init];
        wordRelations=[[NSMutableArray alloc] init];
        wordLinks=[[NSMutableArray alloc] init];
    }
    return self;
}

//Somewhere in Suseran:
-(void)fillStuff
{
    ...
    Vassal *vassal=[Vassal new];
    for (int i=0;i<[originalDataString length];i++)
    {
        ...
        [vassal.wordRelations addObject:anItem];
        ...
    }
    int errorTest=[vassal.wordRelations count];
    if (errorTest==0)
    {
         //breakpoint here. Program NEVER comes here
    }
    [bigArrayOfVassals addObject:vassal];
}
//these arrays are never touched again but here:
-(void) getVassalstuff:(NSMutableString*)codeOfDesiredVassal
{
    Vassal *aVassal;
    for (int i=0;i<[bigArrayOfVassals count];i++)
    {
            aVassal=bigArrayOfVassals[i];
            if ([codeOfDesiredVassal isEqualToString:aVassal.wordCode)
            {
                  int errorTest=[aVassal.wordRelations count];
                  if (errorTest==0)
                  {
                         //yay! this breakpoint sometimes is hit, sometimes not,
                         //depending on code's mood. Why is this happening to me? :,(
                  }
            }
    }
}

【问题讨论】:

  • 一行代码胜过五行解释:-)
  • 没有理由期望“关闭”项目会有“关闭”地址。堆不能那样工作。
  • (我的猜测是您在其他地方有该数组指针的副本,并且您正在通过该指针副本修改数组。您需要了解指针(地址)和对象之间的区别本身(那个地址的房子)。你可以有很多指向一个给定对象的指针,并且通过一个所做的修改被所有人看到。)
  • 那里 :) 希望现在更清楚了。对不起,我之前没有输入任何代码,想解释一下会更好。
  • 我看不到 bigArrayOfVassals 的声明

标签: objective-c


【解决方案1】:

我发现您拥有可变的属性(这本身就是一个坏主意,除了特定情况)并且您正在保留它们。

可变性意味着如果您将数组设置为基于其他数组的属性,并且如果更改了原始数组,则属性中的数组也会更改。可能是因为您没有显示任何代码,所以我不知道您正在清空原始数组,从而更改您作为属性拥有的数组

解决方案:

我首选的解决方案是为您的属性使用这些类的不可变版本; NSString、NSArray 而不是保留使用副本

第二种解决方案是将属性保留为可变属性,但为每个属性编写一个自定义设置器,用于存储您传入的对象的mutableCopy

在这两种情况下,您的属性将是用于设置属性的对象的副本,因此如果对象在您的类之外更改,它不会影响您的类的属性。

在评论后编辑添加

如果您将您的财产声明为

@property (copy) NSArray wordRelations;

那就简单写

vassal wordArray = tempArray;

会做同样的事情,并且更干净,更易读..

【讨论】:

  • 会尝试所有这些,非常感谢。填充初始值后不会更改任何数据。数组只是数据文件的副本,填充后永远不会更改。事实上,我 this 接近于从文件中读取信息而不是使用数组 - '现在让它工作,稍后优化' :)
  • 如果它们在添加后从未改变 - 将它们设为可变是没有意义的。
  • 好吧,我把 wordRelations 改成了 NSArray。到目前为止没有更多的错误 :) 谢谢人 :D (作为一个偶然发现类似问题的旅行者的旁注,我创建了一个 NSMutableArray *temp,在那里加载了所有数据,然后诀窍是附庸。 wordRelations=[NSArray arrayWithArray:tempArray] 蛮蛮力的吧? ;)
猜你喜欢
  • 1970-01-01
  • 2016-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-03
相关资源
最近更新 更多