#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
}*/