Objective-C - 为什么添加两个字符串导致崩溃?

时间:2017-03-08 23:27:51

标签: ios objective-c nsarray

将新字符串追加到旧字符串会导致崩溃。 (如果我这样做StructIOS.server = @""; StructIOS.server = [StructIOS.server stringByAppendingString:@".stackoverflow.com"];,则异常有效。)

struct.h:

struct iOS {
  __unsafe_unretained NSString *input_url;
  __unsafe_unretained NSString *use_url;  
  __unsafe_unretained NSString *server;
};
struct iOS StructIOS;

ViewController.m:

StructIOS.use_url = @"relay/pincode/apicode/accesskey/1/2/3/99/../900";
NSArray *work_array = [StructIOS.use_url componentsSeparatedByString:@"/"];
StructIOS.server    = [work_array objectAtIndex:0];
if([StructIOS.server length] > 0) {
  NSLog(@">>> 4: %@", StructIOS.server); // OK!!
  StructIOS.server = [StructIOS.server stringByAppendingString:@".stackoverflow.com"]; // FAIL!!
  NSLog(@">>> 5: %@", StructIOS.server);  
}

输出:

>>> 4: relay
crash

预期输出:

>>> 5: relay.stackoverflow.com

编辑:以下方式无故障运行

NSString *fool_ios;

// read from NSString type
StructIOS.server = fool_ios;

// save to NSString type
fool_ios = StructIOS.server;

2 个答案:

答案 0 :(得分:3)

答案是双重的:

  • 不要在Objective-C Structs中存储对象。 ARC不会为他们管理记忆。
  • 不要使用unsafe_unretained,除非你完全明白它的作用以及你需要它的确切原因。

只需将您的变量设置为类的实例变量。这将使他们变得强大,这就是你想要的。

编辑:

请注意,在Swift中,将对象存储在Struct中是有效的。 Swift能够在结构内部管理它们,而C则不能。

编译器强制您使用__unsafe_unretained时,您可能会做错事。 (也有例外情况,但在您的理解水平上,您应该假装__unsafe_unretained不存在。)

答案 1 :(得分:1)

他们为什么__unsafe_unretailed? componentsSeparatedByString()可能会在内部创建一些由于使用__unsafe_unretained而未获得所有权的子字符串,因此当componentsSeparatedByString函数超出范围时,它们将被删除。 第4行的日志纯粹是机会和好运,因为字符串被释放但仍然存在于该内存位置。 如果将结构重写为一个简单的类(继承自NSObject),它应该可以工作。