ARC причиняет мне боль

Я понимаю, что есть учебники, но они, кажется, никогда не углубляются.

Сейчас у меня есть приложение, которое позволяет выставлять счета. Однако из-за динамического характера типов данных я сохраняю это как общий объект в основном пользовательском классе, а не как отдельный класс. Каждый счет-фактура содержится в NSMutableDictionary, который может содержать как можно больше или меньше объектов-членов. Существует так много разных типов счетов-фактур, что мы решили, что лучше всего сделать это.

Проблема, с которой мы столкнулись сейчас, заключается в том, что когда один счет-фактура выполнен, а другой создан, пользовательский интерфейс для этих элементов, похоже, сохраняет предыдущие значения счета-фактуры, хотя в конце счета-фактуры я установил NSMutableDictionary на ноль.

Базовый процесс: с помощью нескольких контроллеров представления в различной последовательности я устанавливаю входное значение в NSTextFields как NSStrings как значения для ключей в основном NSMutableDictionary и перехожу к следующему соответствующему экрану.

Эти NSTextFields объявлены неатомарными, сильными.

Их значения устанавливаются с

[myNSMutableDictionary addObject:textField.value forKey:@"thisValue"];

Поскольку в ARC ничего не высвобождается явно, я позаботился о том, чтобы ничего не выделять и не инициализировать.

Каждому экрану onDidShow присваиваются текстовые поля с соответствующим значением в NSMutableDictionary.

Я ожидаю, что во время текущего счета текстовые поля не будут содержать старые значения, а при успешной отправке счета в облачную службу весь счет будет пуст. Никогда не сохраняется на устройстве (за исключением фонового режима).

Что я получаю в результате установки NSMutableDictionary на ноль, так это то, что экраны, кажется, сохраняют либо свои предыдущие значения, иногда ноль, но чаще всего значение предыдущего счета.

Есть ли удобный метод для установки всех членов на ноль, или я должен:

Объявите NSMutableDictionary неатомарным, сильным в моем общем менеджере, Alloc/Init счет-фактура NSMutableDictionary, когда я хочу новый, но объявите все IBOutlets неатомарным, слабым (чтобы назначения в одном или другом направлении не сохранялись) и убедитесь, что я нужно ли выделять объект для добавления в NSMutableDictionary, чтобы они как-то тоже объявлялись слабыми? Может случиться так, что, например, мне нужно сохранить NSArray в NSMutableDictionary, я

[myArray alloc] initWithObjects:value1, value2, nil]];

Я хочу сказать, что даже если я установил счет-фактуру равным нулю, значение1 и значение2 кажутся зомбированными, но переназначаются после второго прохода кода.


Пример кода: в User.h у меня есть свойство:

@property (nonatomic, strong) NSMutableDictionary *currentInvoice;

в User.m я создаю экземпляр во время метода «init»:

currentInvoice = [[NSMutableDictionary alloc] initWithCapacity:1];

При создании нового счета (в InvoiceViewController.m):

User *userInfo = [User sharedManager];
userInfo.currentInvoice = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                   _clientId, @"clientId",
                                   _clientType, @"clientType",
                                   _txtClientName.text, @"clientName",
                                   keyContactName, @"keyContactId",
                                   orderTypeNum, @"orderType",
                                   _keyContact.text, @"keyContact",
                                   _problemDescription.text, @"problemDescription",
                                   _dateOfService.text, @"startDate",
                                   _startTime.text, @"startTime",
                                   _endTime.text, @"endTime", nil];

(Кстати, я думаю, что решил свою проблему, так как я никогда не создаю новый экземпляр userInfo.currentInvoice, просто копирую старый, его члены, не упомянутые здесь, вероятно, все еще в такт)

В другом месте InvoiceViewController.m метод, который фактически отменяет процесс выставления счета:

- (IBAction) dismissViewController:(id)action: {
     User *userInfo = [User sharedManager];
     userInfo.currentInvoice = nil;
}

В InvoiceStepTwoViewController.m другой контроллер с другими аспектами того же счета:

@property (strong, nonatomic) IBOutlet UILabel *clientName; // in the .h, of course
@property (strong, nonatomic) IBOutlet UITextView *textView; // in .h, used to capture data

- (void)viewDidAppear {
    User *userInfo = [User sharedManager];        
    _clientName.text = [userInfo.currentInvoice objectForKey:@"clientName"];
}

После небольшого изменения и захвата значений,

- (IBAction)finishStepTwo:(id)sender {
    [userInfo.currentInvoice addEntriesFromDictionary:[NSDictionary dictionaryWithObjectsAndKeys:_textView.text, @"nerdspeak", nil]]; // so that NSMutableDictionary.currentInvoice objectForKey:@"nerdspeak" will contain _textView.text's value... but will currentInvoice own this object now? Will invoiceStepTwoViewController retain this as long as is possible?
}

Мой вопрос; мои viewControllers (их намного больше) непреднамеренно сохраняют значения из-за @property (сильное, неатомарное) и никогда не отпускают (потому что viewDidUnload никогда не вызывается), и поэтому данные, кажется, не повторно инициализируются, ИЛИ это потому, что когда я добавляю новый счет, я на самом деле не восстанавливаю, а просто копирую другие значения?


person James Perih    schedule 08.10.2013    source источник
comment
Можете ли вы показать код? Тяжело читать такие стены текста.   -  person Joel Fischer    schedule 08.10.2013
comment
Вы уверены, что ваша проблема действительно связана с ARC? Возможно, вам просто нужно перезагружать данные на каждом экране, если они изменены. Возможно, используйте NSNotificationCenter для отправки уведомления на все видимые экраны о необходимости обновления всякий раз, когда счет-фактура изменяется/удаляется и т. д.   -  person Wolfgang Schreurs    schedule 08.10.2013
comment
Что вы имеете в виду, и я позаботился о том, чтобы ничего не выделять и не инициализировать? Вам по-прежнему нужно выделять и инициализировать свои объекты с помощью ARC.   -  person Monolo    schedule 08.10.2013
comment
Это ARC в том, что на мои объекты ссылаются дольше, чем если бы я вручную освобождал их, когда они больше не нужны. Но я сделал предположения о жизненном цикле NSMutableArray, а не предусмотрел возможность управления событиями жизненного цикла. Поэтому я добавил методы в User.h, где currentInvoice является переменной экземпляра shareManager, вместо того, чтобы повторно создавать экземпляр в другом месте и рисковать тем, что контроллер станет последним владельцем.   -  person James Perih    schedule 09.10.2013


Ответы (1)


Без большого количества исходного кода это выглядит так, как будто это не имеет ничего общего с ARC, поэтому изменение объявлений @property (т.е. strong на weak) не повлияет.

Похоже, ваш «источник данных», из которого заполняется ваш пользовательский интерфейс, представляет собой NSMutableDictionary. И похоже, что вы устанавливаете этот словарь на nil, а затем назначаете его новому NSMutableDictionary, который содержит данные нового счета. Это звучит солидно.

Однако изменение значения NSMutableDictionary не приведет к автоматическому изменению значений ваших элементов пользовательского интерфейса (например, self.textLabel.text). Вам понадобится метод, который работает аналогично методу reloadData UITableView в том смысле, что вы вызываете его при обновлении источника данных (т. е. словаря), и он соответствующим образом управляет обновлением пользовательского интерфейса.

Итак, похоже, что это связано не с ARC, а с естественным поведением таких объектов, как UILabel.

Надеюсь это поможет...

person Alfie Hanssen    schedule 08.10.2013
comment
Помечено как ответ, потому что я понимаю, что не полностью устанавливаю это как ноль и переназначаю новый NSMutableDictionary. Я добавил методы в User.h для initInvoice, deleteInvoice и restoreInvoiceFromPlist, чтобы только User.m отвечал за управление жизненным циклом объекта currentInvoice, а не какой-либо другой viewController. Это должно устранить любую добровольную путаницу в отношении собственности. - person James Perih; 09.10.2013