使用copy属性会导致分段错误

时间:2013-10-18 19:27:49

标签: ios objective-c cocoa-touch

我已经启动了Master Detail应用程序并且保持生成的代码不变。我创建并添加了另外两个类:book类(包含标题,作者和摘要的NSString)以及数据控制器类(包含用于存储书籍的可变数组)。

在阅读Apple doc和其他人之后,我对@property属性的理解是这样的:

  1. strong - 默认,创建对象的所有权
  2. 弱 - 替代强,用于避免保留周期
  3. copy - 创建现有对象的副本并获得该
  4. 的所有权
  5. 非原子 - 忽略任何类型的线程安全
  6. 当使用copy属性声明@property AJKBook并且我不明白原因时,此代码会在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
    

1 个答案:

答案 0 :(得分:3)

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

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

你必须考虑是否真的需要复制当前的书。如果我认为某些内容被命名为current,则表明您不想复制。如果唯一的作业来自[[AJKBook alloc] init];副本则完全没有意义。