Одиночный класс DataLoader - устанавливает значения из Core Data в AppDelegate, однако не может получить доступ к переменным DataLoader в других классах - PullRequest
0 голосов
/ 17 января 2012

Я ломал голову и много искал, но пока не повезло.

По сути, я настроил Core Data для загрузки данных из базы данных sqlite в моем классе AppDelegate в общие переменные в одноэлементном классе с именем DataLoader.

У меня также есть основной класс, называемый GameScene, который также будет использовать данные DataLoader.

Я пытаюсь сделать следующее:

  • загрузить данные изDB (используя фоновый поток) и сохраняйте результаты в одноэлементных переменных класса DataLoader (в частности, NSMutableArray)
  • Таким образом, данные загружаются при переходе сцен в область главного меню
  • В GameSceneЯ пытаюсь получить доступ к данным, хранящимся в синглтоне DataLoader, и использовать эти данные в игре.

Моя проблема заключается в том, что, хотя я вижу, что храню объекты в классе AppDelegate, я неКажется, он не может вернуть объекты в классе GameScene.Обычно заканчивается ошибкой EXC_BAD_ACCESS.

Я действительно ищу какой-то пример чего-то похожего или если у вас есть какие-либо идеи.

Если вам нужны примеры кода, дайте мне знать.

Спасибо, Прас.

* EDIT - фрагменты кода *

DataLoader.h

#import <Foundation/Foundation.h>
#import "cocos2d.h"

@interface DataLoader : NSObject {

}

//setup singleton
+(DataLoader *) sharedDataLoader;
@property (nonatomic, retain) NSMutableArray * veHint;//2 characters

DataLoader.m

#import "DataLoader.h"
#import <CoreData/CoreData.h>

@implementation DataLoader
@synthesize veHint;

static DataLoader * myDataLoader = nil;

+(DataLoader *) sharedDataLoader{

    if(myDataLoader == nil){
        myDataLoader = [[[DataLoader alloc]init]retain];
    }
    return myDataLoader;
}

-(id) init
{
    if((self = [super init])){
        veHint = [NSMutableArray arrayWithCapacity:10];
    }
    return self;
}

AppDelegate.mm

#import "AppDelegate.h"
#import "GameScene.h"
#import "RootViewController.h"
#import "Word.h"
#import "DataLoader.h"
-(void) applicationDidFinishLaunching:(UIApplication*)application
{
//other standard stuff here...

//my load data method using data loader
[self getRandomData];

//other standard stuff here...

// Run the intro Scene
[[CCDirector sharedDirector] runWithScene: [GameScene node]];
}

//other standard methods for Core Data

//Random data loader

-(void) fetchRandomData: (NSString *) searchInteger{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSLog(@"fetching random data for word size: %@", searchInteger);

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Word" inManagedObjectContext:managedObjectContext];
    [request setEntity:entity];

    //setup predicate
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY %K == %@", @"size", searchInteger];
    [request setPredicate:predicate];

    NSError *error = nil; 
    NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error]; 
    NSLog(@"fetch results count = %i", [fetchResults count]);
    [request release];

    NSMutableArray * results = [NSMutableArray arrayWithCapacity:10];
    NSMutableArray * fetchedIndexes = [NSMutableArray arrayWithCapacity:10];
    //get the total count, randomize selection of 10 results from the list

    int j = 0;
    while (j<10) {
        int index = arc4random() % [fetchResults count];
        //get only unique values
        if ([fetchedIndexes containsObject:[NSNumber numberWithInt:index]] == false)     {
            [fetchedIndexes addObject:[NSNumber numberWithInt:index]];

            Word * word = (Word *) [fetchResults objectAtIndex:index];
            //NSLog(@"j = %i, index = %i, wordsize = %@, wordstring = %@",j, index, word.size, word.wordString);
            [results addObject:word];
            j++;

        }
    }
    //set dataloader 
    [[DataLoader sharedDataLoader] setVeHint:results];

    [pool drain];   

}

Также необходимо упомянуть, что EXC_BAD_ACCESS находится на вызове [утечка пула] в AppDelegate.mm.

Заранее спасибо за помощь.

Ответы [ 2 ]

0 голосов
/ 17 января 2012

Проблема, вероятно, где-то в коде (я думаю, что это связано с памятью / областью видимости, как слишком ранний выпуск и т. Д.).На самом деле не должно иметь значения, как вы получаете доступ к своим данным, если все их части должным образом «управляются с памятью».

Я могу показать вам, как я делаю этот вид управления данными.

Я обычно называю это DataManager:

DataManager.h

#import <Foundation/Foundation.h>

@interface DataManager : NSObject {
    NSDate *someDate;
}

@property (nonatomic, retain) NSDate *someDate;

+(DataManager*)sharedInstance;
- (void)loadSettings;
- (void)saveSettings;

@end

DataManager.m

#import "DataManager.h"

static DataManager *dataManagerInstance;

@implementation DataManager

@synthesize someDate = _someDate;

// singleton method
+(DataManager*)sharedInstance {
    if(!dataManagerInstance) {
        dataManagerInstance = [[DataManager alloc] init];
    }
    return dataManagerInstance;
}

- (void)saveSettings {
    // save your data   
}

- (void)loadSettings {
    // load your data
}

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

Обновление: ОК, поэтому вы добавили фрагменты кода, и проблема, очевидно, заключается вэта строка:

[[DataLoader sharedDataLoader] setVeHint:results];

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

Вы должны либо написать другой метод установки, который делает копию results и помещает элементы вveHint

или

сохранить results после передачи его в DataLoader следующим образом:

[[DataLoader sharedDataLoader] setVeHint:[results retain]];

Однако это решение (и ваше) создает утечку памяти, поскольку вы сохранили veHint в DataLoader и переписали его в своем делегате (вы полностью потеряли ссылку на veHint).

0 голосов
/ 17 января 2012

Базовые данные не являются потокобезопасными по умолчанию. Если вы пытаетесь использовать его в нескольких потоках, убедитесь, что вы знакомы с рекомендациями Apple .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...