我最近在我的一个类中重写了一些代码,这给了我一个NSString错误。这就是我现在所拥有的:
我的班级标题:
@interface MyViewController : UITableViewController {
NSString *myString;
}
@property (nonatomic, retain) NSString *myString; // Or copy instead of retain.
@end
并实施了一些方法:
- (void)viewDidLoad {
myString = @"This is";
if (something) {
myString = [NSString stringWithFormat:@"%@ a string.", myString]; // *1
}
[myString retain]; // <-- Why do I have to retain/copy here?
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
/* Some code for creating a UITextView called myTextView */
// ..and then setting the text property:
myTextView.text = myString; // <-- Crashes here if I don't retain/copy in viewDidLoad.
}
}
经过一些调试后我发现我必须保留/复制NSString。
如果我想稍后使用它,为什么我必须在viewDidLoad中保留/复制NSString?
另外,我注意到如果我删除标记为* 1的行,我不必保留/复制。
答案 0 :(得分:1)
如果您使用合成的setter方法分配变量,它将自动为您保留NSString
:
if (something) {
self.myString = [NSString stringWithFormat:@"%@ a string.", myString]; // *1
}
答案 1 :(得分:1)
您更好地理解这一点的一种方法是在私有属性前加上下划线_myString并将您的属性保存为myString - 这样可以很容易地计算出正在使用的属性或属性。
由于你似乎只是在课堂上使用这个值,我会质疑为什么你有一个属性,因为我认为这是混乱的根源。
如果您已经设置了前缀,那么您将始终知道_myString在分配时需要保留,myString将自动保留。
* 1处的行正在用新字符串替换myString的值,由于某种原因,在处理第二个方法中的代码之前,这个值是自动释放的。我不记得确切的原因,但我认为第一次分配不会发生这种情况,因为你创建了一个带有@“This is”的字符串文字,它不是自动释放的。
我希望这会有所帮助。
答案 2 :(得分:0)
您可以使用将自动释放/保留的保留属性访问者
- (void)viewDidLoad {
self.myString = @"This is";
if (something) {
self.myString = [NSString stringWithFormat:@"%@ a string.", myString]; // *1
}
// no need to retain
}
当你删除标记为* 1的行时它没有崩溃的原因是因为myString仍然指向@"This is"
,这是一个litteral,它在程序的整个持续时间内存在于内存的一角。永远不会被破坏,因此内存位置仍然有效。