从NSDate到NSString的转换,属性上的核心数据迁移未正确显示字符串 [英] Conversion from NSDate to NSString with Core-Data Migration on Attribute Not Displaying the String Appropriately

查看:43
本文介绍了从NSDate到NSString的转换,属性上的核心数据迁移未正确显示字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很长的问题我很抱歉;我不知道如何在不包含大量代码和图像的情况下对此进行解释。



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



应用程序的模型为:



交易实体



日期实体



年份实体



年份实体具有一个称为yearOfEvent类型的属性 NSDate 并更新了我的应用程序(已经在应用程序商店中),我将yearOfEvent更改为 NSString



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



这通常可以正常工作,但还不足够。



我的应用程序是两个选项卡的 UITabBarController ,其中两个选项卡都是 UITableViewControllers 。第一个是按时间顺序排列的条目的时间轴。第二个选项卡应该仅显示已输入的年份。因此,如果用户有2014年,2013年和2012年的条目,则将在日期标签中的单元格中看到这些条目,当您点击该单元格时,它将显示该年份的条目。这就是我要在此处更改的内容。该应用由用户填充,将一些信息添加到 UITextFields 中,并从 UIDatePicker 中选择一个日期,该日期保存到核心数据,然后使用 NSFetchedResultsController 更新表。



问题



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



我遵循了这个问题的公认答案:我怀疑代码的最后部分来自该答案应该放在您需要添加永久存储(传递您的 NSPersistentStore 的URL)之前(例如 NSURL * destinationStoreURL )添加到您的 NSPersistentStoreCoordinator 中。也就是说,在您的核心数据栈中的代码行之前,应该类似于...

  NSPersistentStore * persistentStore = [self.persistentStoreCoordinator 
addPersistentStoreWithType:NSSQLiteStoreType
配置:无
URL:destinationStoreURL
options:options];

现在解决您的问题-


日期选项卡未正确设置年份,并且年份中的单元格为空


我有两个问题...



在您的 NSFetchResultsController 运行后,您是否可以登录( NSLog fetchedObjects 的值,以检查您是否实际上从 NSFetchedResultsController ?可能是数据转换不成功,您的FRC返回 nil 吗?例如:

  NSLog(@获取的对象是:%@,self.fetchResultsController.fetchedObjects); 

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



让我知道您的工作方式。 ..是否从 NSFetchedResultsController 接收数据,以及是否已成功将数据传递到 configureCell 方法。 / p>

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


I'm sorry for the long question; I have no idea how to explain this without including lots of code and images.

I am working on updating my app and because I discovered an issue relating to dates, I had to change an Attribute from NSDate to NSString. I'm using Core Data for my application.

The model of the application is:

Transaction Entity

Date Entity

Years Entity

The Year Entity has an attribute which is called yearOfEvent of type NSDate and with the update to my app (already in the app store), I am changing the yearOfEvent to NSString.

A bit of research and an answer to another question informed me that I have to do the migration myself.

This is mostly working, but is not quite there yet.

My application is a two-tabbed UITabBarController where both Tabs are UITableViewControllers. The first is a "Timeline" of chronological ordered entries. The second tab is supposed to display only the years that have been entered; so if a user has entries with 2014, 2013 and 2012, you'll see those in the cells in the Dates Tab and when you tap on that cell, it shows you the entries with that year. That's what I'm trying to change here. The app is populated by the user adding in some information into UITextFields and picking a date from the UIDatePicker which gets saved to Core-Data and then the Table updates using NSFetchedResultsController.

Problem

Right now, when I have my app from the App Store running with data and then migrate to the new version of my app with the custom migration, the Timeline is fine, but the cells of the Dates TableViewController have the labels showing blank years. The number of cells is correct, but the years are blank.

I followed the accepted answer in this question: Example or explanation of Core Data Migration with multiple passes? with the first bit of the code, but I'm not sure where to put the second part (final part of the code).

So in my Model class, I have:

- (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;
}

So in my case, I'm extracting the "year" out of the Date Entity because the yearOfEvent is now a string.

Also, I have no idea where to place the rest of the code in the accepted answer with the migration.

For clarity, here's my NSFetchedResultsController which sets the dates:

- (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;

}

In the MappingModel, I've left the default value expression for the YearstoYears entity and made sure to set the Custom Policy to be the Model class I created (Model.h/m).

Any guidance on this would be really appreciated.

Notes - The reason I have a Date and a Year tab was for formatting throughout the app. I'm sure I may be able to get away with having just a Date and then extracting the "year" out of that into an NSString. I will get to do that, but for now, I just want the migration to work appropriately.

  • To reiterate, the problem is, if I am running an older version of the app and I migrate to this newly built version, the Dates tab does not correct set the years and the cells are blank for the year.

解决方案

I have not undertaken a heavyweight migration before, instead preferring to use lightweight migration. I congratulate you on tackling this detailed process.

There is a book that I highly recommend - from The Pragmatic Bookshelf – "Core Data, 2nd Edition, Data Storage and Management for iOS, OS X, and iCloud" (Jan 2013) by Marcus S. Zarra, and in particular Chapter 3 titled "Versioning and Migration".

Regarding your question about the location for the final part of the code for the answer to this SO question... Example or explanation of Core Data Migration with multiple passes? I suspect the final part of the code from that answer should be placed before you need to add your persistent store (pass the URL for your NSPersistentStore) (in that example the NSURL *destinationStoreURL) to your NSPersistentStoreCoordinator. That is, before the line of code in your Core Data stack that would look something similar to this...

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

Now on to your problem -

the Dates tab does not correct(ly) set the years and the cells are blank for the year

I have two questions...

After your NSFetchResultsController has run, are you able to log (NSLog) the value for fetchedObjects to check whether you are actually receiving any data from your NSFetchedResultsController? It may be that the data conversion is not successful and your FRC is returning nil? For example:

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

Also, in your configureCell: method, are you able to log the value for your local variable NSString * stringFromDate?

Let me know how you go... whether or not you are receiving data from your NSFetchedResultsController and whether this is successfully passed to the configureCell method.

Once we know the answer to my questions, I can hopefully help you work out a solution.

这篇关于从NSDate到NSString的转换,属性上的核心数据迁移未正确显示字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆