Objective c 为NSString分配内存?

Objective c 为NSString分配内存?,objective-c,cocoa,memory,Objective C,Cocoa,Memory,我是新手,我有点好奇我应该如何管理下面所示的本地NSString变量和类对象中关联的实例变量的内存。我的代码工作得很好,但对最佳实践很好奇 编辑为包含完整的代码,没有什么特别的,就像我说的,我只是好奇在这个上下文中我是否应该对NSString对象执行alloc/release // MAIN ------------------------------------------------------------------- ** #import <Foundation/Foundatio

我是新手,我有点好奇我应该如何管理下面所示的本地NSString变量和类对象中关联的实例变量的内存。我的代码工作得很好,但对最佳实践很好奇

编辑为包含完整的代码,没有什么特别的,就像我说的,我只是好奇在这个上下文中我是否应该对NSString对象执行alloc/release

// MAIN ------------------------------------------------------------------- **
#import <Foundation/Foundation.h>
#import "PlanetClass.h";

int main (int argc, const char * argv[]) {

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSString *planet_01_Geek;
    NSString *planet_02_Geek;

    // Create planets
    PlanetClass *newPlanet_01 = [[PlanetClass alloc] init];
    [newPlanet_01 setGeekName:@"StarWars"];
    PlanetClass *newPlanet_02 = [[PlanetClass alloc] init];
    [newPlanet_02 setGeekName:@"Dune"];

    // Query a planet
    planet_01_Geek = [newPlanet_01 geekName];
    planet_02_Geek = [newPlanet_02 geekName];

    // Print details
    NSLog(@"Planet Geek    = %@", planet_01_Geek);
    NSLog(@"Planet Geek    = %@", planet_02_Geek);

    // Clean up
    [newPlanet_01 release];
    [newPlanet_02 release];
    [pool drain];
    return 0;
}

这将取决于您如何设置“geekName”的属性。我假设它只是返回对类中现有成员的引用,而不是创建副本?如果是这样的话,您就不必担心在代码中发布任何东西


您只需担心在dealloc()中为它所在的类释放“geekName”成员。

变量是免费的。局部变量由编译器为您分配;实例变量由运行时作为实例的一部分进行分配

在变量中放置指针的对象不是自由的;您可能需要释放它们。是否需要释放对象取决于。

阅读。9个简单的段落,解释你需要知道的一切

因为geekName不以“alloc”或“new”开头,也不包含“copy”,所以它应该返回一个您不“拥有”的字符串。因此,您不需要(事实上,也不能)释放它,也不能存储对它的引用。您可以从所使用的方法返回它,在这种情况下,您的方法名称也不应以“alloc”或“new”开头,或包含“copy”

如果您希望保留它,您必须通过调用retain获得它的所有权,或者因为它是NSString,所以最好是copy。如果将其指定给“复制/保留”属性,则可能会自动执行此操作

在您现在发布的代码中,您在setter中犯了一个错误。您的setter应该复制输入参数,例如:

- (void)setGeekName:(NSString*)gName {
    if ( geekName != gName ) {
        [geekName release];
        geekName = [gName copy];
}
然后,您还需要一个释放geekName的dealloc例程:

- (void) dealloc
{
    [geekName release];
    [super dealloc];
}
或者,您可以使用Objective C属性。而不是您的界面显示:

- (NSString*) geekName;
- (void) setGeekName:(NSString*)gName;
使用属性:

@property (nonatomic, copy) NSString* geekName;
让系统为您合成setter和getter,而不是实现setter和getter:

@synthesize geekName;

您仍然需要dealloc方法来释放geekName。

根据您如何使用这两个局部变量,您可能需要更多的内存管理

按照代码的读取方式,您将本地变量设置为两个类对象返回的指针。如果您正确编写了
newPlanet*
类,那么在释放类时应该释放字符串对象。如果您的两个局部变量尝试使用指针,则会出现问题,因为对象不再存在

两种可能的更正:

1。明确保留字符串

由于直接分配了局部变量,因此您应该明确地保留对象:

planet_01_Geek = [[newPlanet_01 geekName] copy];
planet_02_Geek = [[newPlanet_02 geekName] copy];
我在这里指定copy是因为这是保持对象不变的首选方法,否则,如果原始变量改变,局部变量也会改变

2。使用属性(首选)

这是我首选的方法:实例变量的
retain
copy
assign
然后由类处理

正确声明属性,即:

@property (nonatomic, copy) NSString *planet_01_Geek;
@property (nonatomic, copy) NSString *planet_02_Geek;
在实现中使用
@synthesis

然后使用属性语法分配变量

self.planet_01_Geek = [newPlanet_01 geekName];
self.planet_02_Geek = [newPlanet_02 geekName];
这样,正确的内存管理规则将在分配时应用,合成的访问器方法也将负责释放当前分配给局部变量的任何对象

self.planet_01_Geek = [newPlanet_01 geekName];
self.planet_02_Geek = [newPlanet_02 geekName];
编辑-显示更多课程详情后的注释

setgekname:
方法中,您正在泄漏内存。当您分配一个指向局部变量的新指针时,您并没有向曾经在其中的对象发送释放。一种更好的方法(使用
保留
而不是
复制
保持简单:

- (void)setGeekName:(NSString *)gName {
    [gName retain]; // Hold on to the object that is passed in.
    [geekname release]; // Let go of your current object.
    geekName = gName; // Now allocate the new object.
}

我明白了,我的类接口如下所示,所以你的意思是我真的应该为执行[geekName release]的类提供一个dealloc方法;我在想,当我发布planetClass对象(即[newPlanet_01 release];)@interface planetClass:NSObject时,它可能会被释放{float gravity;float mass;char*name;NSString*geekName;}干杯gary@fuzzygoat-取决于您最初是如何分配该字符串的。如果您使用alloc()或类似的方法,则需要释放它。如果您是从静态“引号字符串”分配的,则不需要释放它。您好,Abizern,我刚刚删减了代码(这是唯一的早期学习内容)并将其全部发布在上面。我现在正在阅读您的回复,非常感谢。我才刚刚开始(确切地说是上周),我知道@synthetic和properties,但还没有看到,我想它们在第9章中,我仍然在3:)没关系,当你说到那部分的时候,请记住这一点。嗨,嗯,我当时的印象是,我正在设置一个现有的项目,该项目是在我从类中创建行星对象时创建的。我是否正确地认为,现在发生的事情不是修改现有的NSString对象,而是创建一个新的对象,除非是旧的object与新对象具有相同的值,在这种情况下,我们只使用旧对象。此外,当您第一次运行代码时,是否存在NSString对象(可能是在创建对象时创建的)。我只是有点好奇,在这种情况下,我将发布什么。在Objective-C中,您可以安全地向
nil
对象发送消息。
- (void)setGeekName:(NSString *)gName {
    [gName retain]; // Hold on to the object that is passed in.
    [geekname release]; // Let go of your current object.
    geekName = gName; // Now allocate the new object.
}