何时保留 NSString?

发布于 12-12 11:35 字数 218 浏览 0 评论 0原文

当 NSString 对象作为参数传入时,我是否应该始终执行 retainrelease:

-forExample:(NSString*)str{
    [str retain];

    //do something

    [str release];
}

?我应该在何时何地使用它?

When an NSString object is passed in as an argument, should I always do retain and release:

-forExample:(NSString*)str{
    [str retain];

    //do something

    [str release];
}

or not? Where and when should I use this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

温馨耳语2024-12-19 11:35:55

该对象的引用计数不会在此方法的过程中发生变化,因此没有理由将其发送retain。来自 Apple 的内存管理文章(你绝对应该看一下):

如果您从程序中的其他地方接收到一个对象,通常可以保证它在接收它的方法或函数内保持有效。如果您希望它在该范围之外保持有效,则应该保留或复制它。如果您尝试释放已释放的对象,您的程序将崩溃。

仅当需要将对象保留在当前范围之外时,才需要保留该对象。

- (void) forExample: (NSString *)theString {
    // Will need this object later. Stuff it into an ivar and retain it.
    // myString = [theString retain];    
    // For NSString, it's actually better to copy, because this
    // could be a _mutable_ string, and it would in fact be best to use
    // the setter for the ivar, which should deal with the memory management:
    [self setMyString:theString];

    // Do things...

    // Don't release.
}

如果您保留了一个对象,那么当您不再需要它时,您需要发送它release

- (void) otherExample {
    [myString doYourStringThing];
    // If you don't need the string past this point (which would be slightly
    // unusual -- it leaves an ivar unset) release it and set it to nil.
    // [myString release]; myString = nil;
    // Again, it would be best to use the setter:
    [self setMyString:nil];
}

// Generally you keep ivars around until the instance is deallocated,
// and release them in dealloc
- (void) dealloc {
    [myString release];
    [super dealloc];
}

The reference count of that object isn't going to change over the course of this method, so there is no reason to send it retain. From Apple's Memory Management essay (which you should definitely look over):

If you receive an object from elsewhere in your program, it is normally guaranteed to remain valid within the method or function it was received in. If you want it to remain valid beyond that scope, you should retain or copy it. If you try to release an object that has already been deallocated, your program crashes.

You only need to retain an object when you need it to stick around past the current scope.

- (void) forExample: (NSString *)theString {
    // Will need this object later. Stuff it into an ivar and retain it.
    // myString = [theString retain];    
    // For NSString, it's actually better to copy, because this
    // could be a _mutable_ string, and it would in fact be best to use
    // the setter for the ivar, which should deal with the memory management:
    [self setMyString:theString];

    // Do things...

    // Don't release.
}

If you have retained an object, you then need to send it release when you no longer need it.

- (void) otherExample {
    [myString doYourStringThing];
    // If you don't need the string past this point (which would be slightly
    // unusual -- it leaves an ivar unset) release it and set it to nil.
    // [myString release]; myString = nil;
    // Again, it would be best to use the setter:
    [self setMyString:nil];
}

// Generally you keep ivars around until the instance is deallocated,
// and release them in dealloc
- (void) dealloc {
    [myString release];
    [super dealloc];
}
狼亦尘2024-12-19 11:35:55

您永远不应该这样做,因为,就像一个优秀的开发人员一样,您要跟上 Objective-C 的最新趋势并使用 自动引用计数。自动引用计数无需手动调用保留/释放,并且随 LLVM 3.0 和 Xcode 4.2 一起提供。

如果出于某种原因,您想要像此处一样使用手动内存管理,则在大多数情况下不应手动调用 retainrelease。通常,可以根据自己的判断进行判断,而不是单独保留每个论点。

唯一一次这可能是个好主意是,如果您的方法在某个时刻调用回调或可能在您使用它之前释放参数的东西。例如,如果您的函数采用一个块并在执行期间调用该块,则可能会出现这种情况。如果该块释放作为参数传递的对象,然后您在调用该块后使用该对象,则该参数本质上是一个悬空指针。

此类场景的示例

- (void)myFunction:(NSString *)foo block:(void (^)())callback {
    [foo retain];
    callback();
    // .. do some stuff
    [foo release];
}

- (void)myCallingFunction {
    NSString * myVariable = [[NSString alloc] initWithString:@"Test"];
    [self myFunction:myVariable block:^ {
        [myVariable release];
    }];
}

如您所见,代码 [myVariable release] 将在 // .. do some stuff 之前到达评论。

You should never do either, because, like a good developer, you are keeping up with the latest trends in Objective-C and using Automatic Reference Counting. Automatic Reference Counting removes the need to manually call retain/release, and comes with LLVM 3.0 and Xcode 4.2.

If, for some reason, you want to use manual memory management like you are doing here, you should not manually call retain and release in most cases. Usually, it is okay to use your judgement and not retain every argument individually.

The only time when this might be a good idea is if your method is, at some point, calling a callback or something that may release the argument before you get to use it. This could be the case if, for instance, your function takes a block and calls that block during its execution. If that block releases the object that was passed as an argument, and you then use that object after calling the block, the argument is essentially a dangling pointer.

Example of such a scenario:

- (void)myFunction:(NSString *)foo block:(void (^)())callback {
    [foo retain];
    callback();
    // .. do some stuff
    [foo release];
}

- (void)myCallingFunction {
    NSString * myVariable = [[NSString alloc] initWithString:@"Test"];
    [self myFunction:myVariable block:^ {
        [myVariable release];
    }];
}

As you can see, the code [myVariable release] would be reached before the // .. do some stuff comment.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文