stringByAppendingString 和保留困境

Posted

技术标签:

【中文标题】stringByAppendingString 和保留困境【英文标题】:stringByAppendingString and retain dilemma 【发布时间】:2013-07-08 21:22:22 【问题描述】:

我将发布使用自动释放著名方法 stringByAppendingString 的示例方法的缺点 3 变体。(xcode 4.6.2.ios 项目中的非弧示例项目)

示例块 1:什么都不返回。只是一个奇怪的指向什么都没有。但不是 null。 示例块 2:也不返回任何内容! 样本块 3:返回 A1A2A3。正如预期的那样,但我认为它有泄漏。 我的问题是: a) 示例方法 1 在 MAC 项目中按预期工作。但在 IOS 项目中没有。 b) 样品块 3 - 包括泄漏? c) 查看示例块 2 中的 cmets。word_ 变为 A1、A1A2 并且什么都没有。为什么? d) 你会用不同的方式编写你自己的相同方法的代码吗?我正在寻找安全的标准方法。

谢谢。


示例块 1
-(NSString*)sampleMethod

    NSString *word_=@"";
    NSString *a1=@"A1";
    NSString *a2=@"A2";
    NSString *a3=@"A3";

    word_=[word_ stringByAppendingString:a1];// word_ is A1
    word_=[word_ stringByAppendingString:a2];// word is nothing but another pointer
    word_=[word_ stringByAppendingString:a3];// word is nothing too but pointer changed.
    return word_;

示例块 2

-(NSString*)sampleMethod

    NSString *word_=@"";
    NSString *a1=@"A1";
    NSString *a2=@"A2";
    NSString *a3=@"A3";

    word_=[word_ stringByAppendingString:a1];// word_ is A1
    word_=[[word_ stringByAppendingString:a2]retain];// word is A1A2
    word_=[[word_ stringByAppendingString:a3]retain];// word is nothing !
    return word_;

示例块 3

-(NSString*)sampleMethod

    NSString *word_=@"";
    NSString *a1=@"A1";
    NSString *a2=@"A2";
    NSString *a3=@"A3";

    word_=[[word_ stringByAppendingString:a1]retain];// word_ is A1
    word_=[[word_ stringByAppendingString:a2]retain];// word_ is A1A2
    word_=[[word_ stringByAppendingString:a3]retain];// word_ is A1A2A3
    return word_;//returns as expected but I think leaks method in this method.


我的回答:只是因为我没有做错任何事情。并且通过调试过程步骤非常清晰地收集了变量值。

但不知何故它在清理项目后解决了。希望这可以为某人节省几个小时。或者不知道内存芯片地址可能出了问题。

【问题讨论】:

如果你的代码没有做它应该做的事情,在断点中放置并检查它,如果你发现它没有按照代码所说的那样做,是时候清理了。 仅供参考,写这个的惯用方式是NSString *word_ = [NSString stringWithFormat:@"%@%@%@", a1, a2, a3] 我认为这只是一个了解内存管理工作原理的示例。否则他可以返回@"A1A2A3"。 你是如何检查这些字符串的? 【参考方案1】:

第一种方法是正确进行内存管理的唯一方法。第二个泄漏两个,第三个泄漏三个 NSString 实例。如果您没有从第一个方法中获得字符串“A1A2A3”,则错误位于该方法之外。

对于您发送的每条保留消息,您还必须在同一方法中发送释放或自动释放消息,除非您的方法名称以 alloc 或 copy 开头。在这种情况下,调用者需要释放返回的对象。

【讨论】:

Sample Block 1 在 Mac App 中返回 A1A2A3。但是 IOS 中的空字符串。(返回一个奇怪的指针,它不会给出任何错误,但会像空字符串一样对待) 好吧。我确定这不是一场噩梦。我只是一一收集值并在这里报告。清理项目后。第一个样品块按预期工作。我无法确定原因。【参考方案2】:

a) 哪个样本块 3 - 包含泄漏?

在您的示例中每次使用 -retain 都是出乎意料的,可能会导致泄漏。

b) 看看 Sample Block.word_ 中的 cmets 变成 A1,A1A2 而什么都没有。为什么?

请仔细检查。

c) 你会用不同的方式为你自己编写相同的方法吗?我正在寻找安全的标准方法。

您可以使用可变字符串,例如:

- (NSString*)sampleMethod

    NSMutableString * word = NSMutableString.string;
    NSString *a1=@"A1";
    NSString *a2=@"A2";
    NSString *a3=@"A3";

    [word appendString:a1];
    [word appendString:a2];
    [word appendString:a3];

    return [NSString stringWithString:word];

或格式字符串:

- (NSString *)sampleMethod

    NSString *a1=@"A1";
    NSString *a2=@"A2";
    NSString *a3=@"A3";

    return [NSString stringWithFormat:@"%@%@%@", a1, a2, a3];

然后根据您的实际输入进行混合和匹配。

【讨论】:

NSMutableString.string 在逻辑上不正确:点符号只能用于访问属性。 @RamyAlZuhouri 这实际上只是您喜欢的编码约定——不是不正确或不合逻辑的。 @RamyAlZuhouri:Apple 的文档从不这么说,实际上提供了相反的例子(例如array.count)。点语法是调用访问器的通用方法,无论它们是否是声明属性的一部分。如果是访问器,则使用点符号在语义上是正确的。【参考方案3】:

第二个和第三个块包含泄漏。一般规则是你保留你想拥有的东西,当你不再需要它时释放它。第一个块非常好:您返回一个自动释放的字符串,如果调用者想要拥有它,它将由调用者保留,否则,它将在将被清理的第一个自动释放池中释放。

在第二个区块中你正在这样做:

word_=[[word_ stringByAppendingString:a2]retain];// word is A1A2
word_=[[word_ stringByAppendingString:a3]retain];// word is nothing !

字符串@"A1A2" 的保留计数为 2,在下一次自动释放池耗尽时,它的保留计数为 1,但是您丢失了对它的任何引用,因此这是一个泄漏。至于保留字符串@“A1A2A3”,这也是不正确的:调用者将决定是否要保留它。出于同样的原因,第三块不正确。

【讨论】:

我也有同样的感觉:样本块 1 是应该的。但示例块 1;没有返回任何问题。 什么都不返回是什么意思? Sample Block 1 在 Mac App 中返回 A1A2A3。但是 IOS 中的空字符串。(返回一个奇怪的指针,它不会给出任何错误,但会像空字符串一样对待)

以上是关于stringByAppendingString 和保留困境的主要内容,如果未能解决你的问题,请参考以下文章

NSDate 和 TimeZone 问题

追加到 NSString 方法的开头

根据选定的表视图行更新 UILabel

iTunes 符号链接到本地​​化应用程序

AVPlayerItem 一次只能占据玩家队列中的一个位置

iOS怎样找到自己的沙盒