我想知道下面第1行和第2行之间的区别:
_subtitle = @"Test"; //Line 1
_subtitle = [NSString stringWithFormat: @"Test"]; //Line 2
如果我问这个问题,那是因为我使用MKAnnotation遇到了问题。在下面的方法中,我尝试更新MKAnnotation的字幕委托属性(非原子,复制和只读)。但是看起来我在使用第2行时得到了一个僵尸而在使用第1行时没有任何东西。所以我的问题是为什么?
- (void) initCoordinateWithAddress:(NSString*)address;
{
self.address = address;
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString: address completionHandler:^(NSArray *placemarks,NSError *error)
{
CLPlacemark *place = [placemarks objectAtIndex:0];
_coordinate = place.location.coordinate;
_title = self.address;
_subtitle = @"Test"; //Line 1: don't crash
_subtitle = [NSString stringWithFormat: @"Test"]; //Line 2: crash
//_subtitle = [[NSString stringWithFormat: @"[%.2f,%.2f]", self.coordinate.latitude, self.coordinate.longitude] copy];
_isInit = YES;
[self.customDelegate didCalculateCoordinate: place.location.coordinate forAnnotation: self];
}];
}
我实际上已经通过使用方法副本修复了我的问题,但我仍然不明白第1行和第2行之间有什么区别,如果有人能帮我理解差异是什么,我将不胜感激。
编辑:
1-我没有使用ARC
2- _subtitle来自@synthesize subtitle = _subtitle;字幕是MKAnnotation协议的一部分,属性非原子,只读和复制
此致 西里尔
答案 0 :(得分:2)
如果您不使用ARC,答案很简单,就是Anoop Vaida写的。但是,我认为需要进一步解释。
这一行
_subtitle = @"Test";
创建对字符串文字的引用。如果你在当前的基础实现中保留其保留计数的峰值,你会发现它是一个非常大的数字(我认为NSIntegerMax)。如果-release
和-retain
的代码遇到保留计数的此值,则它们不会递减或递增。因此,字符串文字具有无限的生命周期。
这一行:
_subtitle = [NSString stringWithFormat: @"Test"];
创建一个您不拥有的字符串。除非您采取措施声明所有权,否则它可能随时消失,最有可能在自动释放池耗尽时消失。您的选项是创建一个您拥有的字符串
_subtitle = [[NSString alloc] initWithFormat: @"Test"];
或保留它。
_subtitle = [NSString stringWithFormat: @"Test"];
[_subtitle retain]; // Can be combined with the previous line if you like.
或复制
_subtitle = [[NSString stringWithFormat: @"Test"] copy];
请注意,在所有情况下,您需要在覆盖它之前释放_subtitle的先前值,否则您将收到泄漏,例如
[_subtitle release];
_subtitle = [[NSString alloc] initWithFormat: @"Test"];
这就是拥有房产更好的原因。仅仅因为MKAnnotation字幕属性是只读的,并不意味着你不能用你自己的读/写属性覆盖它。 e.g。
@interface MyAnnotation : NSObject <MKAnnotation>
// other stuff
@property (readwrite, copy, nonatomic) NSString* subtitle;
@end
如果你然后合成它,你将获得所有正确的内存管理代码,你可以做到
[self setSubtitle: [NSString stringWithFormat: @"test"]];
或者,如果必须使用点符号
self.subtitle = [NSString stringWithFormat: @"test"];
答案 1 :(得分:1)
我只是想知道第1行和第2行之间的区别 波纹管:
_subtitle = @“测试”; //第1行
_subtitle = [NSString stringWithFormat:@“Test”]; //第2行
如果你问上面这两个是相同的。
在检查代码时,差异非常明显。
您正在创建一个新的autorelease
d subtitle
,一旦该区块结束就会被释放。
答案 2 :(得分:0)
如果您查找initWithFormat:
的文档,则会将您链接到Formatting String Objects,其中包含许多示例。
这基本上允许(s)printf样式的格式字符串,如下所示:
NSString *string1 = [[NSString alloc] initWithFormat:@"A string: %@, a float: %1.2f",
@"string", 31415.9265];
// string1 is "A string: string, a float: 31415.93"
关键是通过在字符串参数之后添加,
来指定参数。
答案 3 :(得分:0)
'[NSString stringWithFormat:]'允许您在字符串中添加变量,例如:
int myVar = 3;
NSString *myString = [NSString stringWithFormat:@"This number is %i", myVar];
结果字符串将是(例如,如果你是NSLog它):“这个数字是3”
但你不能这样做:
NSString *myString = @"This number is %i", myVar;
哪会出现错误。
答案 4 :(得分:0)
我认为你的解决方案不是要理解字符串初始化是如何工作的,而是更多地讨论块如何处理变量。
当我考虑它时,我想你可能想尝试通过它的属性访问_subtitle而不是它的ivar。
self.subtitle
这应该增加保留计数并保持一切正常。