ARC ми ​​причинява болка

Осъзнавам, че има уроци, но те никога не изглеждат достатъчно задълбочени.

В момента имам приложение, което позволява фактуриране. Въпреки това, поради динамичния характер на типовете данни, аз запазвам това като споделен обект в основен потребителски клас, а не като самостоятелен клас. Всяка фактура се съдържа в NSMutableDictionary, който може да съдържа възможно най-много или по-малко обекти-членове. Има толкова много различни видове фактури, че решихме, че е най-добре да направим по този начин.

Проблемът, който имаме сега, е, че когато една фактура е готова и е създадена друга, потребителският интерфейс за тези елементи изглежда запазва предишните стойности на фактурата, въпреки че в края на фактурата задам NSMutableDictionary на нула.

Основен процес: чрез няколко контролера за изглед в различна последователност задавам стойността, въведена в NSTextFields като NSStrings като стойности за ключове в главния NSMutableDictionary, и преминавам към следващия подходящ екран.

Тези NSTextFields са декларирани като неатомни, силни.

Стойностите им се задават с

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

Тъй като ARC, нищо не се освобождава изрично и аз внимавах да не разпределям и инициирам нищо.

Всеки екран onDidShow присвоява текстови полета със съответната си стойност в NSMutableDictionary.

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

Това, което получавам, в резултат на настройка на NSMutableDictionary на нула, е, че екраните изглежда запазват или предишните си стойности, понякога нула, но най-често стойността на предишната фактура.

Има ли удобен метод за задаване на всички членове на нула или трябва:

Декларирай NSMutableDictionary като неатомични, силни в моя sharedManager, Alloc/Инициализирай фактурата NSMutableDictionary, когато искам нова, но декларирай всички IBOutlets като неатомични, слаби (така че присвояванията в една или друга посока не се запазват) и се увери, че аз трябва ли да разпределя обект, който да бъде добавен към NSMutableDictionary, че те са декларирани по някакъв начин като слаби? Може да се случи, че например трябва да съхраня NSArray в NSMutableDictionary, I

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

Това, което казвам, е, че въпреки че зададох фактурата като нула, value1 и value2 изглеждат зомбирани, но преназначени след второ преминаване през кода.


Примерен код: в 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