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