从NSDate转换为NSString,在属性上进行核心数据迁移,不能正确显示字符串

时间:2014-04-15 10:06:22

标签: ios core-data nsdate nsfetchedresultscontroller

对不起这个长期问题我很抱歉;我不知道如何在不包含大量代码和图像的情况下解释这一点。

我正在努力更新我的应用,因为我发现了与日期相关的问题,我不得不将属性从NSDate更改为NSString。我在我的应用程序中使用Core Data。

该应用程序的模型是:

交易实体

日期实体

年度实体

Year Entity有一个名为year NSDate的yearOfEvent属性,并且我的应用程序更新(已经在应用程序商店中),我将yearOfEvent更改为NSString

一些研究和对另一个问题的回答告诉我,我必须自己进行迁移。

这主要是有效的,但还没有完成。

我的应用是双标签UITabBarController,其中两个标签均为UITableViewControllers。第一个是"时间轴"按时间顺序排列的条目。第二个标签应该只显示已输入的年份;因此,如果用户拥有2014年,2013年和2012年的条目,您将在“日期”选项卡中的单元格中看到这些条目,当您点击该单元格时,它会显示该年份的条目。这就是我试图改变的地方。该应用由用户添加一些信息填充到UITextFields并从UIDatePicker中选择一个保存到Core-Data的日期然后使用NSFetchedResultsController更新表来填充。

问题

现在,当我从App Store运行带有数据的应用程序,然后使用自定义迁移迁移到我的应用程序的新版本时,时间轴很好,但Dates TableViewController的单元格显示为空白的标签年份。细胞数量是正确的,但年份是空白的。

我在这个问题中遵循了接受的答案:Example or explanation of Core Data Migration with multiple passes?带有代码的第一位,但我不确定将第二部分放在哪里(代码的最后部分)。

所以在我的Model类中,我有:

- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance
                                      entityMapping:(NSEntityMapping *)mapping
                                            manager:(NSMigrationManager *)manager
                                              error:(NSError **)error
{
    // Create a new object for the model context
    NSManagedObject *newObject =
    [NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName]
                                  inManagedObjectContext:[manager destinationContext]];

    // do our transfer of nsdate to nsstring
    NSDate *date = self.transaction.dates.dateOfEvent;
    //NSDate *date = [sInstance valueForKey:@"timeStamp"];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

    [dateFormatter setDateFormat:@"y"];
    //NSString *stringFromYear = [formatter stringFromDate:trans.years.yearOfEvent];


    // set the value for our new object
    [newObject setValue:[dateFormatter stringFromDate:date] forKey:@"yearOfEvent"];

    // do the coupling of old and new
    [manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping];

    return YES;
}

所以在我的情况下,我提取了"年"超出Date Entity,因为yearOfEvent现在是一个字符串。

另外,我不知道在迁移的接受答案中将其余代码放在何处。

为清楚起见,我的NSFetchedResultsController设置日期:

- (NSFetchedResultsController *)fetchedResultsController
{
    NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
    if (_fetchedResultsController != nil)
    {
        return _fetchedResultsController;
    }
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Years" inManagedObjectContext:managedObjectContext];
    fetchRequest.entity = entity;
    NSPredicate *d = [NSPredicate predicateWithFormat:@"transactions.years.@count !=0"];
    [fetchRequest setPredicate:d];
    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"yearOfEvent" ascending:NO];

    fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
    fetchRequest.fetchBatchSize = 20;
    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;
    return _fetchedResultsController;
}

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    EnvylopeDatesTableViewCell  *customCell = (EnvylopeDatesTableViewCell *)cell;
    Years *years = [self.fetchedResultsController objectAtIndexPath:indexPath];
    NSString *stringFromDate = years.yearOfEvent;
    customCell.datesLabel.text = stringFromDate;
    customCell.datesLabel.textColor = [UIColor whiteColor];

    UIView *customColorView = [[UIView alloc] init];
    customColorView.backgroundColor = [UIColor darkGrayColor];
    customCell.selectedBackgroundView = customColorView;

}

在MappingModel中,我保留了YearstoYears实体的默认值表达式,并确保将自定义策略设置为我创建的Model类(Model.h / m)。

enter image description here

对此的任何指导都将非常感激。

备注 - 我有一个日期和年份选项卡的原因是整个应用程序格式化。我确信我可以通过只有一个日期,然后提取"年"从那里进入一个NSString。我会这样做,但就目前而言,我只是希望迁移能够正常运行。

  • 重申一下,问题是,如果我正在运行旧版本的应用程序并迁移到这个新构建的版本,则日期选项卡不会更正设置年份并且单元格在一年中为空白。

2 个答案:

答案 0 :(得分:1)

之前我没有进行过重量级迁移,而是更喜欢使用轻量级迁移。我祝贺你处理这个详细的过程。

我强烈推荐一本书 - 来自The Pragmatic Bookshelf - "核心数据,第2版,iOS数据存储和管理,OS X和iCloud" (2013年1月)作者:Marcus S. Zarra ,特别是第3章,标题为" Versioning and Migration"

关于你对这个SO问题的答案的最后部分代码的位置的问题... Example or explanation of Core Data Migration with multiple passes?我怀疑应该在你需要添加之前放置该答案的最后一部分代码您的持久性商店(将NSPersistentStore的网址)(在该示例中为NSURL *destinationStoreURL)传递给您的NSPersistentStoreCoordinator。也就是说,在Core Data堆栈中的代码行之前看起来与此类似......

NSPersistentStore *persistentStore = [self.persistentStoreCoordinator
                        addPersistentStoreWithType:NSSQLiteStoreType 
                        configuration:nil 
                        URL:destinationStoreURL 
                        options:options];

现在问题 -

  

“日期”选项卡无法正确(ly)设置年份,并且单元格在一年中为空白

我有两个问题......

运行NSFetchResultsController后,您是否能够记录(NSLogfetchedObjects的值,以检查您是否确实从NSFetchedResultsController收到了任何数据?可能是数据转换不成功并且您的FRC正在返回nil?例如:

NSLog(@"fetched objects are: %@", self.fetchResultsController.fetchedObjects);

另外,在您的configureCell:方法中,您是否可以记录本地变量NSString * stringFromDate的值?

告诉我你是怎么做的......你是否从NSFetchedResultsController收到数据,以及这是否已成功传递给configureCell方法。

一旦我们知道了问题的答案,我就可以帮助您制定解决方案。

答案 1 :(得分:0)

这是回答你的回答@AndrewBuilder的答案。

感谢您的回答,并对迟到的回复表示歉意。进行自定义迁移是一种非常可怕的方法,特别是因为我对开发还很新。但是,除了我的问题中的代码之外,我设法用一行代码修复它。

当我回到我提到的答案时,我注意到他在转换之前有一个行valueForKey,所以我就这样做了:

- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance
                                      entityMapping:(NSEntityMapping *)mapping
                                            manager:(NSMigrationManager *)manager
                                              error:(NSError **)error
{
    // Create a new object for the model context
    NSManagedObject *newObject =
    [NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName]
                                  inManagedObjectContext:[manager destinationContext]];

    // do our transfer of nsdate to nsstring
    NSDate *date = [sInstance valueForKey:@"yearOfEvent"]; 
    //NSDate *date = [sInstance valueForKey:@"timeStamp"];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

    [dateFormatter setDateFormat:@"y"];
    //NSString *stringFromYear = [formatter stringFromDate:trans.years.yearOfEvent];


    // set the value for our new object
    [newObject setValue:[dateFormatter stringFromDate:date] forKey:@"yearOfEvent"];

    // do the coupling of old and new
    [manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping];

    return YES;
}

就我而言,关键是yearOfEvent。

令人担忧或有趣的是,这就是我必须做的才能让它发挥作用。当我用yearOfEvent NSDate *date = [sInstance valueForKey:@"yearOfEvent"];做到这一点时,它立即开始工作。

我对我的方法持怀疑态度,因为我实际上没有将其余的代码放在我的代码中的任何地方,但迁移工作从版本1.0到1.2.0,1.1.1到1.2.0和1.0到1.1.1到1.2.0。

我必须弄清楚这里发生了什么!