【问题标题】:releasing and retaining NSString* properly正确释放和保留 NSString*
【发布时间】:2011-04-13 16:16:23
【问题描述】:

大家好,我还是 iPhone 开发的新手,但对其他编程语言有丰富的经验。让我大吃一惊的是 Obj-C 内存管理和正确释放/保留。我知道这个概念,我知道“一旦我理解它就会很容易”,但我并不完全在那里,这让我发疯。在这里,我有一段简单的代码,其中包含类和方法,只需将一个字符添加到现有字符串中,该字符串被合成后用作类属性……例如,该类称为 myClass ...

myClas.h

@interface myClass : NSObject {
  @private 
  NSString* someCommonString;
}
@propery (retain, nonatomic) NSString* someCommonString;

myClass.m

...

@synthesize someCommonString;    

- (id) init 
{
   self = [super init];

   if(self)
   {
       someCommonString = [[NSString alloc] initWith String:@"one "];
   }
}

- (NSString*) appendString:(NSString*) stringToAdd
{
    NSString* result = [someCommonString stringByAppendingString: stringToAdd];
    return result;
}

- (void) doTheJob 
{
   NSString* test1 = @"two ";
   NSString* test2 = [[NSString alloc] initWithString: @"three "];
   NSString* test3 = [NSString stringWithFormat:@"four "];

   self.someCommonString = [self appendString:test1];
   self.someCommonString = [self appendString:test2];
   self.someCommonString = [self appendString:test3];

   NSLog(@"%@", someCommonString); 
}

- (void) dealloc
{
   [someCommonString release];
   [super release];
}
...

好的,在我分配 myClass 并执行 doTheJob 方法后,我应该在 someCommonString 类属性中有@“一二三四”。我知道这是有效的,但也正在泄漏。 test1、test2 和 test3 是初始化 NSString 的 3 种方式,只有 test2 应该被释放,这是不言自明的,但我更担心将它们作为参数传递给 appendString 方法时会发生什么。因为我知道我有泄漏,但不知道如何处理 1. stringToAdd 参数 [我应该在 appendString 方法中担心它吗?] 2. 结果 -> 如果我自动释放结果,我不知道结果将在什么时候被释放。 3. appendStringMethod 中的sommeCommonString,我应该保留它、释放它还是不理它?

嗯 :)

【问题讨论】:

    标签: iphone objective-c


    【解决方案1】:

    乍一看,在我看来你并没有发布test2。将它附加到公共字符串后,就不需要再保留它了。

    self.someCommonString = [self appendString:test1];
    self.someCommonString = [self appendString:test2];
    self.someCommonString = [self appendString:test3];
    [test2 release];
    

    另外两个(test1test3)是自动释放的,所以你的线程会在某个时候回收它们。

    就您的 appendString: 方法而言,result 已经自动发布,实际上您可以将实现减少到

    return [someCommonString stringByAppendingString: stringToAdd];
    

    someCommonString 完全不受操作影响。 stringByAppendingString:selfstringToAdd 的串联中返回一个new autoreleased 字符串。

    希望有帮助

    【讨论】:

    • 非常感谢!虽然那个 stringByAppendingString 没有自动释放
    【解决方案2】:

    ...但我更担心将它们作为参数传递给 appendString 方法时会发生什么。因为我知道我有泄漏,但不知道如何处理
    1. stringToAdd 参数 [我应该在 appendString 方法中担心它吗?] ...

    -appendString: 中没有泄漏。您正在传递stringToAdd 而没有保留它,这没关系。 result 是自动释放的,您无需对其执行任何操作。

    2。结果 -> 如果我自动释放结果,我不知道结果会在什么时候被释放。

    结果已经自动发布,将在当前NSAutoreleasePool 发布后立即发布。到那时你可以不保留地传递它。

    3。 appendStringMethod 中的 sommeCommonString,我应该保留它、释放它还是不理它?

    别管它,它由访问者管理。但正如 fedmest(你也是)所说:发布 test2

    【讨论】:

      【解决方案3】:

      好吧,您的代码中几乎没有问题,但基本问题是您需要 NSMutableString 字符串,而不是 NSString 才能使您的代码正常工作。

      1. 在init方法中,正确的初始化代码是,

        someCommonString = [[NSMutableString alloc] initWithString:@"one "];

      2. 你必须从init中返回对象(self),否则它不会工作,像这样。

        return self;

      3. 如果你想追加字符串,它应该是 NSMutableString,而不是 NSString。

        [[self someCommonString] appendString:test1];

        [[self someCommonString] appendString:test2];

        [[self someCommonString] appendString:test3];

      4. 在dealloc方法中,你调用super的dealloc方法,而不是释放super。所以就这样改正吧。

        [super dealloc];

      5. 没有必要释放test1test3,因为它们是自动释放

      我写了正确的代码,试试这个。

      @interface myClass : NSObject {
      @private 
          NSMutableString* someCommonString;
      }
      @property (retain, nonatomic) NSMutableString* someCommonString;
      
      - (void) doTheJob;
      @end
      
      
      @implementation myClass
      @synthesize someCommonString;
      
      
      - (id) init 
      {
          self = [super init];
      
          if(self)
          {
              someCommonString = [[NSMutableString alloc] initWithString:@"one "];
          }
      
          return self;
      }
      
      - (NSString*) appendString:(NSString*) stringToAdd
      {
          NSString* result = [someCommonString stringByAppendingString: stringToAdd];
          return result;
      }
      
      - (void) doTheJob 
      {
          NSString* test1 = @"two ";
          NSString* test2 = [[NSString alloc] initWithString: @"three "];
          NSString* test3 = [NSString stringWithFormat:@"four "];
      
          [[self someCommonString] appendString:test1];
          [[self someCommonString] appendString:test2];
          [[self someCommonString] appendString:test3];
      
      
      
          NSLog(@"%@", someCommonString); 
      
          [test2 release];
      }
      
      - (void) dealloc
      {
          [someCommonString release];
          [super dealloc];
      }
      @end
      

      【讨论】:

      • 非常感谢您的努力。抱歉,我打错了几个字,忘了重新输入返回值...有点担心您的重做,使用 [[self someCommonString] appendString ...您正在调用 someCommonString 上的 appendAstring 方法,该方法会生成 urecognized 选择器。 4 我这只有在与 NSString/NSMutableString 的类别一起使用时才有效?我在常规 NSString 上使用 stringByAppendingString 没有问题,但不确定这是否正确?
      • stringByAppendingString 只会将字符串与您的字符串对象连接并返回附加的字符串,但不会更改您的原始字符串内容。
      【解决方案4】:

      这是一种可以帮助您更好地处理 @synthesize 指令所发生的事情的技术。如下更改标题

      @interface myClass : NSObject {
         @private 
         NSString* _bob;
      }
      @property (retain, nonatomic) NSString* someCommonString;
      

      和你的类文件

      @synthesize someCommonString = _bob;  
      

      如果你重新编译你的代码,你会得到构建错误。修复这些,您将突然能够准确地看到您通过综合属性访问的内容以及您直接访问的内容。

      另外,如前所述,您需要在 doTheJob 方法中释放 test2。

      【讨论】:

      • 你也发现了我隐藏在字里行间的疑问!一定会试试这个!,非常感谢!
      猜你喜欢
      • 1970-01-01
      • 2011-01-24
      • 2011-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      相关资源
      最近更新 更多