Singleton 类 DataLoader - 在 AppDelegate 中从 Core Data 设置值,但无法访问其他类中的 DataLoader 变量
Posted
技术标签:
【中文标题】Singleton 类 DataLoader - 在 AppDelegate 中从 Core Data 设置值,但无法访问其他类中的 DataLoader 变量【英文标题】:Singleton class DataLoader - set values from Core Data in AppDelegate, however cannot access DataLoader variables in other classes 【发布时间】:2012-01-16 22:40:09 【问题描述】:我一直在绞尽脑汁,进行了很多搜索,但到目前为止还没有运气。
基本上,我已设置 Core Data 以将数据从 AppDelegate 类中的 sqlite db 加载到名为 DataLoader 的单例类中的共享变量中。
我还有一个名为 GameScene 的主类,它也将使用 DataLoader 数据。
我想要做的如下:
从 DB 加载数据(使用后台线程)并将结果存储在 DataLoader 单例类变量中(特别是 NSMutableArray) 以这种方式在场景转换到主菜单区域时加载数据 在 GameScene 类中,我尝试访问存储在 DataLoader 单例中的数据,并在游戏中使用这些数据。我的问题是,虽然我可以看到我将对象存储在 AppDelegate 类中,但我似乎无法返回 GameScene 类中的对象。通常以 EXC_BAD_ACCESS 错误结束。
我真的在寻找一些类似的例子,或者如果你有任何想法。
如果您需要代码示例,请告诉我。
谢谢, 普拉斯。
*编辑 - 代码片段*
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 中的 [pool drain] 调用中。
提前感谢您的帮助。
【问题讨论】:
是的,示例代码将阐明您的问题并更容易找到问题。 生活中很多事情都可能出错...我不知道该选择哪一个... ;-(您如何尝试访问单例中的数据,以及您的单例如何定义。你用那个单例线程安全吗?这些信息应该可以帮助我们帮助你。 大家好,感谢您的快速回复。该代码与 Ray Wenderlich 的 Core Data 教程 ([raywenderlich.com/934/core-data-tutorial-getting-started][1]) 的 Core Data 非常相似。我有一个加载的 sqlite db。然后我有一个方法 getRandomData(),其中包含 NSFetchRequest。在这种方法中,我获取的结果被过滤,这是我设置 Data Loader NSMutableArray 变量的地方。这个核心数据方法几乎没有偏差,所以我不确定这是否能回答你的问题? [1]:raywenderlich.com/934/core-data-tutorial-getting-started 添加了代码 sn-ps - 抱歉耽搁了。 【参考方案1】:问题可能出在代码的某个地方(我认为它与内存/范围有关,比如发布太早等)。只要您正确地“管理”数据中的每一个部分,您如何访问数据实际上并不重要。
我可以向您展示我是如何进行这种数据管理的。
我通常将其命名为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
我希望你明白了……也许你发布一些代码 sn-ps 以便我们可以找出你的单身人士出了什么问题;-)
更新:好的,所以你添加了代码sn-ps,问题显然出在这一行:
[[DataLoader sharedDataLoader] setVeHint:results];
您将 veHint 设置为 results
,因此您将覆盖 DataLoader 的私有变量。你不应该那样做,因为results
被释放并且DataLoader 丢失了引用。
您应该编写另一个setter方法,复制results
并将元素放入veHint
或
像这样将results
传递给 DataLoader 后保留它:
[[DataLoader sharedDataLoader] setVeHint:[results retain]];
但是,此解决方案(以及您的解决方案)会造成内存泄漏,因为您在 DataLoader
中保留了 veHint
并在您的委托中覆盖它(您完全失去了对 veHint
的引用)。
【讨论】:
就单例而言,上面 septi 给出的示例几乎是我为单例 DataLoader 类提供的代码,除了我有 NSMutableArray 变量和在 NSMutableArray 中返回特定值的方法. 我认为问题在于您如何返回并管理您传递的对象。你真的应该上传一些代码;-) 作为请求添加的代码 sn-ps - 抱歉耽搁了。【参考方案2】:Core Data 默认不是线程安全的。如果您尝试在多个线程上使用它,请确保您熟悉 Apple's guidelines。
【讨论】:
谢谢。我不介意 Core Data 不是单例。事实上,我只是拥有从 App Delegate 类访问 sqlite DB 的标准方法。我只想使用从数据库中获取的结果并在单例类中设置变量,以便我的主游戏场景可以访问过滤后的数据。如果这有意义的话。以上是关于Singleton 类 DataLoader - 在 AppDelegate 中从 Core Data 设置值,但无法访问其他类中的 DataLoader 变量的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 torch Dataloader 获取具有相同类的图片?
pytorch datasets与dataloader阐释说明
Pytorch的Dataset与Dataloader之间的关系