【问题标题】:Using the copy attribute causes a segmentation fault使用复制属性会导致分段错误
【发布时间】:2013-10-27 18:24:45
【问题描述】:

我已经启动了一个 Master Detail 应用程序,并且没有修改生成的代码。我创建并添加了两个额外的类:一个书籍类(包含一个用于标题、作者和摘要的 NSString)和一个数据控制器类(包含一个可变数组来存储书籍)。

阅读Apple doc等后我对@property属性的理解是这样的:

  1. strong - 默认,创建对象的所有权
  2. weak - 替代 strong,用于避免保留循环
  3. copy - 创建现有对象的副本并取得其所有权
  4. nonatomic - 忽略任何类型的线程安全

当 @property AJKBook 使用 copy 属性声明时,此代码会在 addBookToList 中引发分段错误,我不明白为什么。

@interface AJKBookDataController ()

// when current book uses the copy attribute code seg faults in addBookToList
@property (nonatomic) AJKBook  *currentBook;
@property (nonatomic, copy) NSString *currentValue;

- (void)populateBookList;
- (void)addBookToBookList;

@end

@implementation AJKBookDataController

- (id)init
{
    self = [super init];
    if (self) {
        _bookList = [[NSMutableArray alloc] init];
        _currentBook = [[AJKBook alloc] init];
        _currentValue = [[NSString alloc] init];
        [self populateBookList];
        return self;
    }
    return nil;
}

- (void)setBookList:(NSMutableArray *)bookList
{
    // this bit of code ensures bookList stays mutable
    if (_bookList != bookList) {
        _bookList = [bookList mutableCopy];
    }
}

- (void)populateBookList
{
    NSURL *url = [NSURL URLWithString:@"https://sites.google.com/site/iphonesdktutorials/xml/Books.xml"];

    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url];

    [parser setDelegate:self];
    [parser parse];

    NSLog(@"%@", [self.bookList description]);
}

- (void)addBookToBookList
{
    [self.bookList addObject:self.currentBook];
    self.currentBook = [[AJKBook alloc] init];
}
...
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    if ([elementName isEqualToString:@"title"]) {
        // [self.currentBook title:self.currentValue];
        self.currentBook.title = self.currentValue;
    } else if ([elementName isEqualToString:@"author"]) {
        self.currentBook.author = self.currentValue;
    } else if ([elementName isEqualToString:@"summary"]) {
        self.currentBook.summary = self.currentValue;
    } else if ([elementName isEqualToString:@"Book"]) {
        [self addBookToBookList];
    }

    self.currentValue = [NSString stringWithFormat:@""];
}
@end

【问题讨论】:

  • 但是你没有使用复制属性,因为你访问了合成属性,所以字符串没有被复制。您确定代码在第三次崩溃,就像在 if 中一样吗?我觉得没问题。
  • @RamyAlZuhouri 很抱歉,我应该恢复到包含 currentBook 上的 copy 属性的代码。挖掘输出结果:-[AJKBook copyWithZone:]: unrecognized selector sent to instance 0x8982390 我不知道我需要实现自己的复制方法。

标签: ios objective-c cocoa-touch


【解决方案1】:

如果您想为自定义类使用副本,则必须在这些类中实现 – copyWithZone:

但您不必使用copy。通常strong 就足够了。 copy 主要用于 NSString 属性,因为您想防止分配 NSMutableString 并稍后从类外部更改。

您必须考虑是否真的需要复制当前的书。如果在我看来某些东西被命名为current,这强烈表明您不想复制。如果唯一的分配来自[[AJKBook alloc] init];,则副本根本没有意义。

【讨论】:

  • 谢谢。挖掘错误输出可以准确地表明这一点。 -[AJKBook copyWithZone:]: 无法识别的选择器发送到实例 0x8982390
  • 这是另一个更清楚回答的问题。使用副本时是合适的。再次感谢。
猜你喜欢
  • 2019-12-04
  • 2011-11-22
  • 2021-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-18
  • 2021-05-25
相关资源
最近更新 更多