Objective c 当对象超出范围时,NSArray的行为异常

Objective c 当对象超出范围时,NSArray的行为异常,objective-c,memory-management,nsarray,Objective C,Memory Management,Nsarray,我在NSArray中遇到了一个奇怪的问题,数组中的一些对象的成员超出了范围,但其他的没有: 我有一个简单的对象叫做Section。 它有3名成员 @interface Section : NSObject { NSNumber *section_Id; NSNumber *routeId; NSString *startLocationName; } @property(nonatomic,retain) NSNumber *section_Id; @prop

我在
NSArray
中遇到了一个奇怪的问题,数组中的一些对象的成员超出了范围,但其他的没有:

我有一个简单的对象叫做Section。 它有3名成员

@interface Section : NSObject {
    NSNumber *section_Id;   
    NSNumber *routeId;
    NSString *startLocationName;
}
@property(nonatomic,retain)  NSNumber *section_Id;  
@property(nonatomic,retain)  NSNumber *routeId;
@property(nonatomic,retain)  NSString *startLocationName;
@end


@implementation Section

@synthesize section_Id; 
@synthesize routeId;
@synthesize startLocationName;

//Some static finder methods to get list of Sections from the db
+ (NSMutableArray *) findAllSections:{


- (void)dealloc {
    [section_Id release];
    [routeId release];
    [startLocationName release];

    [super dealloc];
}

@end
我使用名为
findAllSection

self.sections = [Section findAllSections];
在“查找所有”部分中,我创建了一些局部变量,用db中的数据填充它们

NSNumber *secId = [NSNumber numberWithInt:id_section];
NSNumber *rteId = [NSNumber numberWithInt:id_route];
NSString *startName = @"";
然后创建一个新节并将这些局部变量的数据存储在该节中

Section *section = [[Section alloc] init];

section.section_Id = secId;
section.routeId = rteId;
section.startLocationName = startName;
然后我将节添加到数组中

[sectionsArray addObject:section];
Section  * section = [self.sections objectAtIndex:row];
然后我清理,释放局部变量和我添加到数组中的部分 [第二次发布]; [rteId释放]; [startName发布]; [locEnd_姓名发布]

[section release];
在循环中对所有部分重复(释放局部变量,每个循环中都完成部分)

方法返回,我检查数组,所有的部分都在那里。我似乎无法深入查看数组中截面对象的值(这可能吗)

稍后,我尝试检索其中一个部分

我从数组中得到它

[sectionsArray addObject:section];
Section  * section = [self.sections objectAtIndex:row];
然后检查值

NSLog(@" SECTION SELECTED:%@",section.section_Id);
但是对
section.section\u Id
的调用崩溃为
section.section\u Id
超出范围

我检查了这个部分对象的其他成员,他们都正常。 经过一些尝试和错误后,我发现通过注释成员变量的释放,对象是OK的

//[secId release];
[rteId release];
[startName release];
[locEnd_name release];


[section release];
我的问题是:

我打扫干净了吗

我应该释放添加到数组中的对象和函数中的局部变量吗

我在这一节的交单行吗

这段代码看起来正常吗?我应该在别处寻找问题吗

我并没有做任何复杂的事情,只是从数据库中填充数组,在表单元格中使用它


我可以对这个版本发表评论,但我更想知道为什么会这样,如果我不应该这样做的话。
secId
唯一被释放的地方是dealloc。

您不应该释放
secId
rteId
startName
secId
rteId
是指向使用返回已自动删除对象的工厂方法创建的
NSNumber
实例的指针。不需要释放静态字符串(即
@“
)。你需要重读这本书。然后再读一遍;-)它将是你的朋友。

你正在释放你不拥有的对象。您应该阅读。

我将附议(第三)阅读内存管理规则的建议

TL;DR版本是您
alloc
的任何内容,在方法名称中使用
init
调用方法是您的责任。例如:

NSString *string = [[NSString alloc] initWithFormat:@"%@", someObject];
在这种情况下,必须释放
字符串
。然而:

NSString *string = [NSString stringWithFormat:@"%@", someObject];
此处自动删除
字符串
。这基本上相当于:

NSString *string = [[[NSString alloc] initWithFormat@"%@", someObject] autorelease];
…意味着下一次通过事件循环时(这意味着可能在函数返回时),系统将为您发送一条
release
消息。苹果称之为“便利方法”

如果你有这样的东西:

NSString *string = @"foo";
然后,
string
指向运行时在程序初始化时创建的NSString实例,在程序终止之前不会超出范围。也不要
release


再次阅读指南并将其添加到书签中。但这应该回答你的直接问题

“巴里也打败了我。不过,他是对的。除了少数例外,您只会释放从
init
copy
new
方法创建的对象。我建议您对任何人使用的内存管理都不太在意。按照Barry链接的内存管理规则进行操作。人们倾向于非正式地重述它们,并且经常说它有点错。例如,kubi只是省略了
copy
mutableCopy
。因此,不要过于依赖于规则的重述。Barry是对的,但只是澄清一下,你不应该发布你正在创建的本地
NSNumber
实例。您仍然应该释放实例变量。通常,您可以通过将nil指定给属性(
self.section\u Id=nil;
)而不是调用实例变量上的
release
)来更时髦地实现这一点。@warrenm,请不要将
nil
指定给属性来释放您的描述器中的实例变量。如果你给你的属性设置器添加了副作用,那么这样做是一件痛苦的事情。标准做法是在
init
dealloc
方法中使用原始实例变量,并在其他地方使用属性访问。我不同意,除非您使用的是KVO。在任何其他情况下,尤其是当您将自定义行为添加到mutator时,您应该仔细检查如何执行最终版本,在这种情况下,您可以根据需要进行更改。否则,就没有理由把这种选择作为一种风格来贬低了。大家干杯//TODO:Friday-R.T.F.M.(阅读Feckin手册)还是R.T.F.MMM(阅读Feckin成员管理手册);)