【问题标题】:Why do weak NSString properties not get released in iOS?为什么弱 NSString 属性没有在 iOS 中发布?
【发布时间】:2012-06-19 19:09:46
【问题描述】:

我编写了以下示例代码来了解 ARC 的工作原理

@property (nonatomic, weak) NSString *myString;
@property (nonatomic, weak) NSObject *myObj;
@end

@implementation ViewController
@synthesize myString = _myString;
@synthesize myObj = _myObj;
- (void) viewDidAppear:(BOOL)animated
{
    NSLog(@"Appearing Obj: !%@!",self.myObj);
    NSLog(@"Appearing String: !%@!",self.myString);
}

- (void)viewDidLoad
{
    self.myObj = [[NSObject alloc] init];
    self.myString = [[NSString alloc] init];
    NSLog(@"Loading Obj %@",self.myObj);
    NSLog(@"Loading String: !%@!",self.myString);
}

但令人惊讶的是,我得到了这些结果:

2012-06-19 15:08:22.516 TESTER[4041:f803] Loading Obj (null)
2012-06-19 15:08:22.517 TESTER[4041:f803] Loading String: !!
2012-06-19 15:08:22.533 TESTER[4041:f803] Appearing Obj: !(null)!
2012-06-19 15:08:22.535 TESTER[4041:f803] Appearing String: !!

如您所见,Obj 已正确释放,但我的字符串(这也是一个弱属性)没有打印出 null...为什么不呢?

【问题讨论】:

  • 您在myString 中设置的字符串是否是字符串文字(类似于@"Hello world!")?

标签: iphone objective-c ios automatic-ref-counting


【解决方案1】:

NSString 使用各种内部技巧来重用对象并避免不必要的分配和复制。它可以做到这一点,因为NSString 实例是不可变的。在这种情况下,可能有一个共享实例来表示 [[NSString alloc] init] 返回的空字符串,并且这个共享实例将作为单例保留在其他地方。

【讨论】:

  • 这似乎有道理。谢谢!
  • 也许有人可以查看 NSString 源代码来确认这一点。
  • 有道理,尽管我认为依赖这种行为并不明智,这似乎只是某种优化的表现,可能会在未来的某个日期发生变化。跨度>
  • 其中一个优化是字符串文字在应用程序的整个生命周期中都存在。此外,创建一个引用字符串文字([NSString stringWithFormat:@"Hello world"];[[NSString alloc] initWithFormat:@"Hello world"];)的新字符串将返回对完全相同的字符串文字的引用(就像我在 my answer 中提到的那样)
  • 我猜当您在文字字符串上调用它时,复制也会产生相同的共享实例?
【解决方案2】:

[[NSString alloc] init] 总是返回 相同 值。您可以自行查看。

NSString *string1 = [[NSString alloc] init];
NSString *string2 = [[NSString alloc] init];
NSString *string3 = [[NSString alloc] init];
NSLog(@"string1 = %p, string2 = %p, string3 = %p", string1, string2, string3)

此代码返回三个相同的地址。就我而言,输出是:

string1 = 0x3e8dd74c, string2 = 0x3e8dd74c, string3 = 0x3e8dd74c

这意味着[[NSString alloc] init] 返回单例。单身人士通常不能被释放。

使用其他方法(如initWithFormat:)创建字符串会生成通常的“非单例”对象,通常可以释放,但有一些例外。

进一步: 寻找源代码(汇编程序):

-[NSPlaceholderString init]:
00040ea4        f64b009c        movw    r0, 0xb89c
00040ea8        f2c00016        movt    r0, 0x16
00040eac            4478        add     r0, pc
00040eae            4770        bx      lr

会是这样的(在 ObjectiveC 中)

-(id)init
{
    return SOME_CONSTANT_VALUE;
}

可能是kCFEmptyString,但我不确定。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-10
    • 1970-01-01
    • 1970-01-01
    • 2021-06-24
    • 2013-05-03
    • 1970-01-01
    相关资源
    最近更新 更多