Как переопределить средство получения / установки свойства в одноэлементном классе Objective C

#ios #objective-c

#iOS #objective-c

Вопрос:

Я создал одноэлементный класс и внутри него в качестве свойства есть объект класса (myRecords). Я хочу выполнить некоторую обработку реализации в способе получения / установки этого свойства.

Как я могу переопределить средство получения / установки этого свойства?

Примечание: Инициализация MyRecord не выполняется внутри одноэлементного класса.

 // singleton.h

@interface mySingleton : NSObject

@property(nonatomic, copy) NSString *name;

@property(nonatomic) myRecords *record;

 (mySingleton *)instance;

@end

// singleton.m
@implementation TRNApplicationContext
 (mySingleton *)instance {

static mySingleton *_instance = nil;

    @synchronized (self) {
        if (_instance == nil) {
            _instance = [[self alloc] init];
        }
    }
    return _instance;
}

-(void) setRecord:(myRecords *)record
{
    self.title = record.name;
    . . .
}

-(myRecords *) record
{
        return self.record;     // Error - EXC_BAD_ACCESS
}

@end

// TestMainViewController.m - Below is Singleton usage

@implementation TestMainViewController

-(void)viewDidLoad
{
 .  .  .
    myRecords *someRecord = [myRecords new];
    someRecord.name = @"test";
    [[mySingleton instance] setRecord:someRecord];
    NSLog(@"value : %@", [[[mySingleton instance] record] name]);
}

@end
  

Комментарии:

1. есть ли у вас следующая строка в вашем setRecord: методе в вашем одноэлементном классе: _record = record , это необходимо для присвоения входящей переменной переменной экземпляра вашего одноэлементного объекта

Ответ №1:

У вас ошибка переполнения стека.

Вам нужно изменить

 -(myRecords *) record
{
    return self.record;  // call this method again and cause infinite recursion 
}
  

Для

 @synthesize record = _record; // usually put this on the line below @implementation
-(myRecords *) record
{
    return _record;     // return the ivar
}
  

Вам также нужно

 _record = record;
  

внутри setRecord:

Комментарии:

1. Спасибо, это сработало. Не могли бы вы, пожалуйста, объяснить, почему @synthesize должен быть добавлен явно. Я предполагал, что о synthesize позаботились, поскольку я использую xcode 5.1.

2. @user3020200 если вы переопределяете оба средства получения и установки, вам нужно @synthesize . в противном случае он не создаст ivar для вас, потому что он может вам не понадобиться.

Ответ №2:

На самом деле вы вообще не переопределяете средство получения / установки. Вы предоставляете свою собственную реализацию, вместо того, чтобы использовать реализацию, предоставленную компилятором. Вы могли переопределить средство получения / установки в подклассе, что было бы очень, очень странным поступком.

Для реализации одиночных элементов я бы рекомендовал следовать обычному шаблону, включающему dispatch_once . Это более эффективно, это признано всеми, и все знают, что это работает.

«myRecords» — очень, очень странное название для класса, который, по-видимому, реализует одну запись. Это будет постоянной причиной путаницы для любого, кто читает ваш код. Аналогично, «MySingleton» — это очень, очень странное название для класса. Что вы собираетесь делать, когда вам нужен другой одноэлементный класс, назовите его myOtherSingleton? Имя должно отражать назначение класса, а не какие-либо детали реализации.

Я бы настоятельно рекомендовал использовать не «новый» метод, а обычный шаблон [[myRecords alloc] init]. Использование распространенных шаблонов делает ваш код более читаемым и придает больше уверенности в коде. Когда я вижу [SomeClass new] Я знаю, что мне нужно очень внимательно прочитать окружающий код.

Средство установки «setRecord» фактически не устанавливает переменную экземпляра _records. Нет причин предоставлять средство получения «записи». Тот, который предоставляется компилятором, подойдет просто отлично. И, как также сообщали другие, вызов средства получения «record» из средства получения «record» приводит к бесконечной рекурсии.

Вся проблема, конечно, не имеет ничего общего с одиночными элементами. У вас был бы точно такой же сбой для любого класса с средством получения, которое вызывает само себя рекурсивно. Вам также следует научиться использовать отладчик Xcode. Самое первое, что вам следовало сделать при обнаружении сбоя, это проверить стек вызовов, и вы бы обнаружили, что средство получения было вызвано средством получения, которое было вызвано средством получения, которое было вызвано средством получения, и так далее до бесконечности.

Ответ №3:

Еще один простой способ сократить ваш код, просто замените два приведенных ниже метода, поскольку вы уже объявили свойство переменной records в файле .h. Итак, просто объявите synthesize той же переменной в файле .m, и это сработает.

     /*  -(void) setRecord:(myRecords *)record
    {
    self.title = record.name;
      . . .
    }

  -(myRecords *) record
    {
    return self.record;     // Error -     
   EXC_BAD_ACCESS
  }*/