Когда использовать средство доступа и когда обращаться к атрибуту напрямую?

#objective-c

#objective-c

Вопрос:

У меня есть этот фрагмент кода в Objective-C, взятый из руководства:

 - (NSFetchedResultsController *)fetchedResultsController {
    if (fetchedResultsController_ != nil) {
        return fetchedResultsController_;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"FailedBankInfo"
                                              inMana&edObjectContext:self.context];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"details.closeDate" ascendin&:NO];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

    [fetchRequest setFetchBatchSize:20];

    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc]
                                                               initWithFetchRequest:fetchRequest
                                                               mana&edObjectContext:self.context
                                                               sectionNameKeyPath:nil
                                                               cacheName:@"Root"];
    self.fetchedResultsController = theFetchedResultsController;
    fetchedResultsController_.dele&ate = self;

    [sort release];
    [fetchRequest release];
    [theFetchedResultsController release];

    return fetchedResultsController_;
}
  

В моем файле объявления у меня есть это:

 @interface FailedBankListViewController : UITableViewController 

<NSFetchedResultsControllerDele&ate&&t; {
    NSFetchedResultsController *fetchedResultsController_;
    NSMana&edObjectContext *context_;
}

@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
@property (nonatomic, retain) NSMana&edObjectContext *context;

@end
  

Мой вопрос в том, почему я должен писать код таким образом, как только мы получаем прямой доступ к атрибуту, как только мы используем средство доступа:

 if (fetchedResultsController_ != nil) {
    return fetchedResultsController_;
}

// AND

self.fetchedResultsController = theFetchedResultsController;
  

и это не работает:

 if (self.fetchedResultsController != nil) {
    return self.fetchedResultsController;
}

// AND

fetchedResultsController_ = theFetchedResultsController;
  

Я не понимаю, когда я должен использовать средство доступа, а когда я должен использовать средство доступа?

Заранее спасибо за вашу помощь!

Ответ №1:

Строка

 self.fetchedResultsController = theFetchedResultsController;
  

эквивалентно вызову

 [self setFetchedResultsController:theFetchedResultsController];
  

В зависимости от природы свойства иногда допустимо обойти метод setter внутри самого класса — например, в dealloc — но в большинстве случаев вы хотите перенаправить все настройки через этот один метод, чтобы он мог управлять правами собственности и любыми другими связанными задачами администратора.

Если бы вы действительно хотели получить доступ к ivar напрямую здесь, как минимум, вам нужно было бы убедиться, что объект был retain отредактирован надлежащим образом — в коде, показанном вам release после настройки. И вполне возможно, что в setFetchedResultsController происходят и другие вещи. Но без кода мы можем только догадываться. (Например, я не могу отделаться от мысли, что настройка строки self в качестве делегата должна находиться в установщике, а не здесь.)

И наоборот, строка

  return self.fetchedResultsController;
  

эквивалентно вызову

  return [self fetchedResultsController];
  

Должно быть очевидно, почему последнее является плохой идеей внутри самого fetchedResultsController метода — вы получаете бесконечный регресс.

Ответ №2:

accessor являются setter и &etter методами для свойства. итак, когда вы создаете свойство, то для настройки и получения значений свойства вам нужны методы средства доступа (имеется в виду setter и &etter).

в коде эта строка

 self.fetchedResultsController = theFetchedResultsController;
  

здесь вызывается установщик.