Переменная экземпляра не возвращает значение в приложении iOS

Эта проблема может быть связана с переменной экземпляра, не сохраняющей значение в приложении iOS < / а>.

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

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

--

Я объявил переменную экземпляра NSDictionary "providerData" в заголовке своего класса:

#import <UIKit/UIKit.h>

@interface ViewController : UITableViewController {

    NSDictionary *providerData;

}

@property (nonatomic, retain) NSDictionary *providerData;

- (void)loadProviderDataSource:(NSString *)providerName;

@end

В моей реализации я использую viewDidLoad для чтения словаря из файла plist, проверяю значение «provider_preference» и затем вызываю [self loadProviderDataSource:providerPreference]:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Retrieve the user's provider preference from defaults:
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    // Set a default value for provider preference if the user didn't explicitly set one:
    NSString *providerPreference = [[NSString alloc] initWithString:@"foo"];

    if ([defaults stringForKey:@"provider_preference"]) {
        providerPreference = [defaults stringForKey:@"provider_preference"];
    }

    // Load provider data from the relevant plist:
    [self loadProviderDataSource:providerPreference];
}

Все это работает нормально (с помощью NSLog я вижу, что файл plist читается правильно и что в loadProviderDataSource передается правильное значение providerPreference.

Реализация loadProviderDataSource выглядит следующим образом:

- (void)loadProviderDataSource:(NSString *)providerName
{
    // Set the filename and path for the data source:
    NSString *dataSourceFileName = [[NSString alloc] initWithFormat:@"data-%@.plist",providerName];
    NSString *dataSourcePath = [[NSBundle mainBundle] bundlePath];
    dataSourcePath = [dataSourcePath stringByAppendingPathComponent:dataSourceFileName];

    // Read the provider data:
    self.providerData = [[NSDictionary alloc] initWithContentsOfFile:dataSourcePath];

    NSLog(@"provider data entry count 1: %d", [self.providerData count]);
}

На этом этапе NSLog показывает мне, что в providerData есть 2 записи.

Однако, когда мне нужно установить ячейки для представления таблицы, NSLog в следующем коде показывает мне, что providerData имеет 0 записей:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    NSLog(@"provider data entry count 2: %d", [self.providerData count]);

    return cell;
}

В loadProviderDataSource я пробовал использовать:

self.providerData = [[NSDictionary alloc] initWithContentsOfFile:dataSourcePath];

и:

[self setProviderData:[[NSDictionary alloc] initWithContentsOfFile:dataSourcePath]];

... ни одна работа, и я все еще получаю это в моем журнале:

provider data entry count 1: 2
provider data entry count 2: 0
provider data entry count 2: 0

Любые идеи?


person Willem    schedule 15.07.2011    source источник
comment
Куда вы звоните loadProviderDataSource и как загружаете ViewController экземпляр?   -  person Deepak Danduprolu    schedule 15.07.2011
comment
Если вы не используете ARC, у вас утечка с этой строкой: self.providerData = [[NSDictionary alloc] initWithContentsOfFile:dataSourcePath];. Вам нужно добавить команду autorelease.   -  person FreeAsInBeer    schedule 15.07.2011
comment
Вы уверены, что значение providerData в cellForRow не равно нулю?   -  person Warren Burton    schedule 15.07.2011
comment
@Deepak: В моей реализации я использую viewDidLoad для чтения словаря из файла plist, проверки значения provider_preference, а затем вызова: [self loadProviderDataSource:providerPreference]; Интерфейс MainWindow.xib моего приложения имеет контроллер навигации, внутри которого находится мой ViewController (который является подклассом класса UITableViewController). Контроллер навигации, в котором находится ViewController, является моим корневым контроллером представления, поэтому он загружается, как только это делает приложение.   -  person Willem    schedule 15.07.2011
comment
@FreeAsInBeer: Спасибо! Добавлю автоспуск.   -  person Willem    schedule 15.07.2011
comment
@Willem providerData установлен в другом месте? Можете ли вы добавить метод viewDiadLoad?   -  person Deepak Danduprolu    schedule 15.07.2011
comment
+1 к вопросу Уоррена. Убедитесь, что self.providerData не равен нулю (каким-то образом) в tableView:cellForRowAtIndexPath:.   -  person cduhn    schedule 15.07.2011
comment
@Deepak: единственное место, где установлен providerData, находится в loadProviderDataSource. Я обновил исходный пост содержимым viewDidLoad.   -  person Willem    schedule 15.07.2011
comment
@Warren, @cduhn: В tableView:cellForRowAtIndexPath ноль, но я не понимаю почему. Единственное место, где я назначаю ему данные, - это loadProviderDataSource. Может быть, что-то не так с объявлением моей переменной экземпляра providerData, и она каким-то образом сохраняет свои данные только для локальной области в каждом методе?   -  person Willem    schedule 15.07.2011
comment
Вы проверили выпуск? Вы где-нибудь выпускаете providerData?   -  person Raxit    schedule 15.07.2011
comment
Попробуйте переопределить метод setProviderData: и поставить там точку останова. Таким образом, мы можем узнать, как оно установлено на ноль.   -  person Ilanchezhian    schedule 15.07.2011
comment
@Raxit: Нет, я его нигде явно не выпускаю. В этом вопросе, правильно ли я говорю, что неатомарные, сохраненные настройки моего объявления @property не приведут к его автоматическому выпуску? Насколько мне известно, вам нужно вручную включить автоматический подсчет ссылок и автозапуск, верно?   -  person Willem    schedule 15.07.2011
comment
@Gomathi: Не повезло, мутатор setProviderData вызывается только один раз из loadProviderDataSource ...   -  person Willem    schedule 15.07.2011
comment
@ Виллем, что означает NSLog(@"%@", self); в журнале loadProviderDataSource: и tableView:cellForRowAtIndexPath:?   -  person Deepak Danduprolu    schedule 15.07.2011
comment
@Deepak: loadProviderDataSource self: <ViewController: 0x83739b0> и tableView:cellForRowAtIndexPath self: <ViewController: 0x8373170>.   -  person Willem    schedule 15.07.2011


Ответы (1)


На основе NSLog(@"%@", self); в обоих методах, которые отображаются следующим образом

loadProviderDataSource

self: <ViewController: 0x83739b0> 

tableView: cellForRowAtIndexPath

self: <ViewController: 0x8373170>

Похоже, вы каким-то образом создаете второй экземпляр ViewController.

Я так понимаю, один из них создан с использованием XIB. Убедитесь, что вы создаете еще один программно.

person Deepak Danduprolu    schedule 15.07.2011
comment
Мое слово. Я не создавал другой экземпляр программно, но, играя в Interface Builder, я добавил два объекта: объект контроллера табличного представления в контроллере навигации и пустой объект. Оба были настроены на мой класс ViewController. Один был установлен как источник данных для UITableView, другой - нет. Я удалил лишний объект, и все работает на 100%, большое спасибо! : D - person Willem; 15.07.2011