iOS - 轻量级迁移 - 无法识别的选择器

时间:2016-05-29 18:57:41

标签: ios core-data

我正在尝试进行轻量级迁移。我按照project一步一步地制作了一个新的tutorial,让事情顺利进行。但现在我在另一个应用程序中,一切似乎都很顺利但是当我尝试访问新字段时,我收到以下错误。

[Promocion setEnlace:]: unrecognized selector sent to instance 0x7fafe40bceb0

我选择了正确的型号。 enter image description here

这是模型Promocion.h

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

/*
@interface Promocion : NSManagedObject

@property (nonatomic, retain) NSNumber * id_promocion;
@property (nonatomic, retain) NSString * descripcion;
@property (nonatomic, retain) NSString * titulo;
@property (nonatomic, retain) NSString * url;
@property (nonatomic, retain) NSString * fecha_inicio;
@property (nonatomic, retain) NSString * fecha_fin;

@end
 */

NS_ASSUME_NONNULL_BEGIN

@interface Promocion : NSManagedObject

// Insert code here to declare functionality of your managed object subclass

//+(id)personaWithContext:(NSManagedObjectContext *)context;

@end

NS_ASSUME_NONNULL_END

#import "Promocion+CoreDataProperties.h"

Promocion.m

#import "Promocion.h"


@implementation Promocion


- (NSComparisonResult)compare:(Promocion *)otherObject {

    NSDateFormatter *dateformat = [[NSDateFormatter alloc] init];
    [dateformat setDateFormat:@"MMMM dd,eeee HH:mm a z"];
    NSDate *dateA = [dateformat dateFromString:self.fecha_inicio];
    NSDate *dateB = [dateformat dateFromString:otherObject.fecha_inicio];

    return [dateA compare:dateB];
}

@end

以下是自动生成的文件 Promocion + CoreDataProperties.h

#import "Promocion.h"

NS_ASSUME_NONNULL_BEGIN

@interface Promocion (CoreDataProperties)

@property (nullable, nonatomic, retain) NSString *descripcion;
@property (nullable, nonatomic, retain) NSString *fecha_fin;
@property (nullable, nonatomic, retain) NSString *fecha_inicio;
@property (nullable, nonatomic, retain) NSNumber *id_promocion;
@property (nullable, nonatomic, retain) NSString *titulo;
@property (nullable, nonatomic, retain) NSString *url;
@property (nullable, nonatomic, retain) NSString *enlace;

@end

NS_ASSUME_NONNULL_END

Promocion + CoreDataProperties.m     #import&#34; Promocion + CoreDataProperties.h&#34;

@implementation Promocion (CoreDataProperties)

@dynamic descripcion;
@dynamic fecha_fin;
@dynamic fecha_inicio;
@dynamic id_promocion;
@dynamic titulo;
@dynamic url;
@dynamic enlace;

@end

AppDelegate.m

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"data.sqlite"];

    //Migration
    NSDictionary *options = @{
                              NSMigratePersistentStoresAutomaticallyOption  :@YES,
                              NSInferMappingModelAutomaticallyOption        :@YES
                              };

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                   configuration:nil
                                                             URL:storeURL
                                                        //options:nil
                                                         options:options//automatic migration
                                                           error:&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.

         Typical reasons for an error here include:
         * The persistent store is not accessible;
         * The schema for the persistent store is incompatible with current managed object model.
         Check the error message to determine what the actual problem was.


         If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.

         If you encounter schema incompatibility errors during development, you can reduce their frequency by:
         * Simply deleting the existing store:
         [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]

         * Performing automatic lightweight migration by passing the following dictionary as the options parameter:
         @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}

         Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.

         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        //abort();
    }

    return _persistentStoreCoordinator;
}

其他信息

我已更新项目版本。

我在哪里访问名为&#34; enlace&#34;

的字段
NSString* className = NSStringFromClass([Promocion class]);
NSEntityDescription *entity = [NSEntityDescription entityForName:className inManagedObjectContext:context];
Promocion* obj = (Promocion*)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:context];

obj.id_promocion = [NSNumber numberWithInt:[[centro objectForKey:@"id_promo"] intValue]];
obj.titulo = [centro objectForKey:@"titulo"];
obj.descripcion = [centro objectForKey:@"descripcion"];
obj.url = [centro objectForKey:@"imagen"];
obj.fecha_inicio = [centro objectForKey:@"fecha_ini"];
obj.fecha_fin = [centro objectForKey:@"fecha_fin"];
obj.enlace = [centro objectForKey:@"enlace"];

我尝试了什么

我更改了Promocion.h以避免使用Promocion + CoreDataProperties.h,但我仍然遇到同样的错误。

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@interface Promocion : NSManagedObject

@property (nonatomic, retain) NSNumber * id_promocion;
@property (nonatomic, retain) NSString * descripcion;
@property (nonatomic, retain) NSString * titulo;
@property (nonatomic, retain) NSString * url;
@property (nonatomic, retain) NSString * fecha_inicio;
@property (nonatomic, retain) NSString * fecha_fin;
@property (nonatomic, retain) NSString * enlace;

@end

另一次尝试

我重新创建Promocion.h删除旧的并使用Editor-&gt;创建一个新的创建NSOjecteManaged子类。它看起来像是在工作。但是当我使用git回滚到最后一次未更新的核心数据提交并将其安装在设备上然后使用新的coredata模型进行最后一次提交升级应用程序时,再次开始失败。该死的我感到非常沮丧。

部分Appdelegate.m

#pragma mark - Core Data stack

// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}

// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"DataModel" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"data.sqlite"];

    //Migration
    NSDictionary *options = @{
                              NSMigratePersistentStoresAutomaticallyOption  :@YES,
                              NSInferMappingModelAutomaticallyOption        :@YES
                              };

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                   configuration:nil
                                                             URL:storeURL
                                                        //options:nil
                                                         options:options//automatic migration
                                                           error:&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.

         Typical reasons for an error here include:
         * The persistent store is not accessible;
         * The schema for the persistent store is incompatible with current managed object model.
         Check the error message to determine what the actual problem was.


         If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.

         If you encounter schema incompatibility errors during development, you can reduce their frequency by:
         * Simply deleting the existing store:
         [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]

         * Performing automatic lightweight migration by passing the following dictionary as the options parameter:
         @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}

         Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.

         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        //abort();
    }

    return _persistentStoreCoordinator;
}

解决方案

最终出错的是我有两个Coredata文件的引用(dunno why)。其中一个仍然是第一版。我已经改变了那个版本,一切都按预期工作。

4 个答案:

答案 0 :(得分:3)

我认为您的错误与轻量级迁移无关,因为您的应用程序不会崩溃 - OnLaunch(对于没有迁移的任何结构更改)但它会为您提供主要与您的模型类相关的运行时错误。

我怀疑您的代码仍在旧类中使用旧生成的模型类或旧类别而没有丢失属性:(#import "Promocion.h"#import "Promocion+creation.h")。

如果您coreData&amp; managedObjects - 在Xcode之前使用先前版本的Xcode 7创建了子类。您可以通过cmd+tap轻松检查#import "Promocion.h"以查看内容。

如果是这样的话就是一个检查清单来解决问题(否则这可能仍然有助于其他类似的问题):

- 搜索和删除(或重命名!)Promocion.h:仅包含动态属性的旧生成文件(使用Xcode7版本之前的版本生成,请参阅下面的详细信息。)

- 检查是否已在该班级上创建了某个类别。"Promocion+Xyz.h"并将所有引用#import "Promocion+Xyz.h"更改为#import "Promocion.h"

- 重新创建managedObject子类。

<强>上下文

在Xcode7之前,每当我们创建一个managedObject子类时,.h都包含动态属性,我们曾经在该类上创建category来添加方法,同时能够重新生成managedObject } subclass,不会丢失我们创建的方法,因为它们属于一个类别。

来自Xocde7 Apple审核了,现在动态属性在ClassName+CoreDataProperties.h,以便在主类上轻松工作/添加方法,而无需添加类别,同时能够重新生成managedObject,因为只重新创建了ClassName+CoreDataProperties.h

所以现在,当我们重新创建以前由旧方法创建的managedObject子类时,我们需要确保引用#import“Promocion.h”正确的文件!。

答案 1 :(得分:0)

读起来似乎没有发生迁移,虽然类文件可能正确,但它们都依赖底层NSManagedObject来拥有属性。

您是否可以从已更新为Model 2的设备获取sqlite文件并检查sqlite文件的结构并查看新属性是否到位?如果它不是那么这将指向迁移未触发,并且可能将错误版本的模型定义为当前。

答案 2 :(得分:0)

最终出错的是我有两个Coredata文件的引用(dunno why)。其中一个仍然是第一版。我已经改变了那个版本,一切都按预期工作。

答案 3 :(得分:-1)

尝试更改AppDelegate的datamodel函数中的行:

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"DataModel" withExtension:@"momd"];

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"DataModel 2" withExtension:@"mom"];