在 CoreData 中传递对象

Posted

技术标签:

【中文标题】在 CoreData 中传递对象【英文标题】:Passing objects in CoreData 【发布时间】:2012-12-31 12:40:34 【问题描述】:

我在我的应用程序中使用 CoreData,它是一对多的关系,我有两个实体,分别称为 foldersfiles。所以一个文件夹可以有很多文件。所以我的第一个视图控制器显示所有文件夹,当单击每个文件夹时,我显示其中存在的文件。

现在其中的所有文件夹和文件都是由用户动态创建的,而不是来自任何数据库或网络服务器。

现在我又多了一个视图控制器,我从应用程序委托打开它,在这里我想显示一些文件。

我知道首先我们应该传递managedObjectContext,它将在应用委托中声明

ViewController *View = [[ViewController alloc]initWithNibName: @"ViewController" bundle:nil]
View.managedObjectContext = self.managedObjectContext;

所以如果我们只传递managedObjectContext,我们是否可以访问文件实体对象,或者我们也必须传递文件实体对象。

现在如您所知,我有两个实体,称为 FolderFile,现在要访问存储在任何文件夹中的文件,我就是这样做的。

NSMutableArray *filesArray = [self.folder.file mutableCopy];

但是现在,我想在anyView中显示我想要的文件,可以二三导航后打开,也可以直接从appDelegate.m打开。

非常清楚,我的问题是如何做到这一点?即如何从 AppDelegate 获取 filesArray。

根据编辑的以下答案。我以这种方式创建了一个 fetchResultsController

- (NSFetchedResultsController *)fetchedResultsController 

    if (m_fetchResultsController != nil) 
        return m_fetchResultsController;
    

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"File" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"alarm" ascending:YES];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];

    [fetchRequest setSortDescriptors:sortDescriptors];
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"alarm!= nil"]];

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    aFetchedResultsController.delegate = self;
    self.fetchResultsController = aFetchedResultsController;

    NSError *error = nil;
    if (![self.fetchResultsController performFetch:&error]) 
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
        
    return  m_fetchResultsController;   

在 ViewDidLoad 和我这样写

- (void)viewDidLoad

    [super viewDidLoad];
   NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) 
        // Update to handle the error appropriately.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    


     NSMutableArray *alarms = [[self.fetchResultsController fetchedObjects]mutableCopy];

    NSLog(@"alarmsCount:%d",[alarms count]);

问候 兰吉特。

【问题讨论】:

编辑你的问题并写下你的疑问;) 检查一下,***.com/questions/14170772/… 嗨,现在我有点忙。我会尽快阅读您的问题。 @flexaddicted,正如您告诉我如何获取所有文件,无论它属于哪个文件夹。所以现在在这样做之后,我可以知道它属于哪个文件夹。假设我有两个文件 A 和 B,来自一个单独的视图控制器中的不同文件夹,我能知道 A 是否属于哪个文件夹。 @flexaddicted ,正如您在下面的答案中所说,如果您有很多文件,最好使用 NSFetchResultsController.File 实体包含一个名为提醒的属性,该属性是 NSDate 类型。实际上我设置了提醒的几个文件,我不想要所有文件,我只想要我设置提醒的文件。因为,如果我在这里访问所有文件,它会变慢。如何做到这一点。我的第二个问题是,我们能否从这个视图中知道文件属于哪个文件夹。 【参考方案1】:

如果您分享更多详细信息,我们可以为您提供帮助,但与此同时...

如果主控制器显示文件夹而细节控制器显示文件,只需将所选文件夹的引用注入细节控制器即可。

比如像这样在detail controller中创建一个属性(需要合成)

@property (nonatomic,strong) Folders* currentFolder;

创建细节控制器时,请执行以下操作

DetailController* detCtr = // alloc-init here
detCtr.currentFolder = // the folder you want to pass in

一些注意事项

使用 Camel Case 表示法。 使用NSFetchedResultsController 延迟加载与表等相关的数据。 以单数形式重命名实体 FilesFolders

编辑

好的,所以如果你想从应用内的任何地方访问你的应用委托,你可以调用

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate someMethod];

在这里,您可以使用在 .h 中声明并在 .m 中合成的公共属性检索您感兴趣的文件夹。

现在,这不是一个很好的方法。 AppDelegate 类将保持原样。

另一种更优雅的方法是创建一个名为 SharedManager(或其他名称)的单例,用于存储需要可视化的 currentFolder

共享管理器看起来像

//.h
@property (nonatomic,strong) Folder* currentFolder;

+ (SharedManager*)sharedInstance;


//.m
@synthesize currentFolder;

+ (SharedManager*)sharedInstance

    static dispatch_once_t once;
    static id sharedInstance;
    dispatch_once(&once, ^
        sharedInstance = [[SharedManager alloc] init];
    );
    return sharedInstance;

那个,导入后,用来设置一个文件夹为当前文件夹

[[SharedManager sharedInstance] setCurrentFolder:theFolderYouWantToShare];

或检索当前文件夹

Folder* theSharedFolder = [[SharedManager sharedInstance] currentFolder];

附:不要滥用单身人士。我使用的单例模式需要 ios 4 及更高版本。

编辑 2

这是我的错。我没看懂这个问题。

如果您需要检索所有文件,您可以创建一个NSFetchRequest,如下所示:

NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"File" inManagedObjectContext:context]; 

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];

NSError *error = nil; 
NSArray *results = [context executeFetchRequest:request error:&error];

其中results 将包含您商店中独立任何文件夹中的所有文件。您可以使用此数组来显示表格中的文件。

如果你有很多文件,我真的建议看看NSFetchedResultsController class。它允许与UITableView 一起延迟加载。

你可以在这里找到一个很好的教程:How To Use NSFetchedResultsController

编辑 3

如何进行提醒?

您应该为您的请求(与 NSFetchedResultsController 一起使用的请求)提供如下谓词

[request setPredicate:[NSPredicate predicateWithFormat:@"reminder != nil"]];

通过这种方式,您可以检索提醒不是nil 的文件。 reminder 是您在模型中使用的属性。

附:检查代码,因为我是在没有 Xcode 支持的情况下编写的。

【讨论】:

您好,谢谢,为此,我已经在我的 Master 和 detailViewController 中完成了这项工作,一切正常。现在对于一些文件,我正在设置提醒,以显示本地通知。所以每当弹出通知时,它们都是本地通知的委托函数,应该写在appdelegate.m中。他们我正在创建此 ThirdViewController 的实例并打开此 ViewController 以显示该特定日期和时间的文件。希望这很清楚。现在将这些文件传递给这个thirdViewController。 @Ranjit 我不明白你的评论。您可以编辑您的问题并在那里提供详细信息吗?谢谢 嗨@flexaddicted,我不想共享文件夹,假设我有两个文件夹,folder1和folder2,然后我在folder1中添加file1,在folder2中添加file2,现在我有一个我想要显示的视图tableView 上存在的所有文件,无论它存在于哪个文件夹中。如何做到这一点,如果我使用单例类,那么我必须再次将这些实体保存在 plist 中的某个位置。希望你能明白。 你在吗? .我有疑问

以上是关于在 CoreData 中传递对象的主要内容,如果未能解决你的问题,请参考以下文章

在没有 managedObjectContext 的视图之间传递 CoreData 对象

如何跨视图传递 CoreData 对象

删除 CoreData 对象

CoreData 预取在属性中没有错误

删除CoreData对象

Objective-C:在 NavigationController 中分层传递 CoreData