objective-c - 在 ARC 下返回 NSString 时如何避免临时对象

标签 objective-c ios nsstring automatic-ref-counting

我有一个具有两个属性的类:

@interface Contact : NSObject {
    NSString *lastname;
    NSString *lastNameUpper;
}

我已将姓氏声明为一个属性(并在 .m 文件中合成它):

@property (nonatomic, retain) NSString *lastname;

但是,我想编写自己的方法来访问 lastNameUpper,所以我声明了一个方法:

- (NSString *) lastNameUpper;

并像这样实现它:

- (NSString *) lastNameUpper {
    if (!lastNameUpper) {
        lastNameUpper = [lastname uppercaseString];
    }
    return lastNameUpper;
}

这一切正常,但由于它经常被调用,所以调用了很多临时对象。有趣的是,Instruments 显示了很多“Malloc (4k)”,并且每次访问 lastNameUpper 时数字都会增加。我还可以看到内存是在 objc_retailAutoreleaseReturnValue 中分配的。

由于在我将我的项目转换为 ARC 之前它工作正常,我假设我必须对方法签名进行一些 ARC 特定的添加,但我似乎无法使其工作。

有什么建议吗?

最佳答案

0:你应该复制你的 NSString 属性:

 @property (nonatomic, copy) NSString * lastname;

I'm guessing that returning the string is implemented by copying it.

不。 不可变 字符串的副本是保留操作。只需在分析器中运行它,看看这会花费多少时间和内存。此外,在这种情况下没有隐式副本。

更新

我在 Lion-64 上对此进行了测试。 uppercaseString 可能会返回一个可变 字符串。

为了安全起见,您可以考虑分配 uppercaseString 结果的副本:lastNameUpper = [[lastname uppercaseString] copy];。这可能会导致更多或更少的分配,具体取决于您在实现中如何使用字符串。如果您的属性复制,则每次分配时都会制作一个副本。简单的概括就是分配一个副本,其余的通常会自行处理。

测试程序

// ARC enabled
#import <Foundation/Foundation.h>

@interface Contact : NSObject
{
    NSString * lastname;
    NSString * lastNameUpper;
}

@property (nonatomic, copy) NSString *lastname;

@end

@implementation Contact

@synthesize lastname;

- (NSString *) lastNameUpper {
    if (!lastNameUpper) {
        lastNameUpper = [lastname uppercaseString];
    }
    return lastNameUpper;
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int n = 0;
        while (n++ < 100000) {
            Contact * c = [Contact new];
            c.lastname = @"skjdhskjdhaksjhadi";
            NSString * lastNameUpper = c.lastNameUpper;
        }
    }

    return 0;
}

关于objective-c - 在 ARC 下返回 NSString 时如何避免临时对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10249633/

相关文章:

ios - 如何修复错误: 7012 Message reply took too long - WCSession WatchOS 3

ios - 如何在 UILabel 中将第一个字母大写?

ios - 如何获取纯 'globe' Unicode 字符

iphone - 来自编码未知的文本文件的 NSString

ios - 读取字典元素的预期方法在 'id<NSFastEnumeration,NSObject>' 类型的对象上找不到

iPhone:如何在 MapKit 上的两点之间画线?

iOS7 静默推送通知不起作用

ios - 解析错误代码 : 155 - Exceeded request limit

ios - 如何在没有任何动画的情况下直接将模态视图呈现为表单

ios - 如何为 SKSpriteNode 创建自定义属性?