ekimneems
ekimneems

Reputation: 25

CoreData issue - unrecognized selector set to instance

I'm inheriting a project from someone else and it was created in an older version of Xcode. Upon upgrading I've found a few things I've had to fix, but this one is stumping me.

I have a CoreData model with classes generated by Xcode (NSManagedObject). I have a Meeting object which contains a speaker attribute using the Speaker class. The relationships are all in place but upon the first attempt at assigning a meeting instance's speaker attribute I get the following:

2016-05-26 16:32:46.276 SignMeIn[7829:316171] -[NSKnownKeysDictionary1 setSpeaker:]: unrecognized selector sent to instance 0x7a9042b0
2016-05-26 16:32:46.288 SignMeIn[7829:316171] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSKnownKeysDictionary1 setSpeaker:]: unrecognized selector sent to instance 0x7a9042b0'
*** First throw call stack:
(
    0   CoreFoundation                      0x033ea494 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x02ea4e02 objc_exception_throw + 50
    2   CoreFoundation                      0x033f4253 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
    3   CoreFoundation                      0x0332989d ___forwarding___ + 1037
    4   CoreFoundation                      0x0332946e _CF_forwarding_prep_0 + 14
    5   SignMeIn                            0x000be242 +[CoreDataManager addSpeakerWithDictionary:forMeeting:] + 1458
    6   SignMeIn                            0x000bf6b6 +[CoreDataManager insertMeetingsFromArray:] + 902
    7   SignMeIn                            0x000b7f5b -[SyncView request:hasBeenTerminatedWithSuccess:forServiceMethod:] + 2203
    8   SignMeIn                            0x0009c0f6 __91+[OnsiteAttendeeAPI callApiMethod:isPost:parametersDictionary:delegate:shouldStartRequest:]_block_invoke.101 + 118
    9   SignMeIn                            0x00070425 -[ASIHTTPRequest reportFinished] + 213
    10  libobjc.A.dylib                     0x02eb9059 -[NSObject performSelector:withObject:] + 70
    11  Foundation                          0x023eb5f8 __NSThreadPerformPerform + 323
    12  CoreFoundation                      0x032fce5f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
    13  CoreFoundation                      0x032f2aeb __CFRunLoopDoSources0 + 523
    14  CoreFoundation                      0x032f1f08 __CFRunLoopRun + 1032
    15  CoreFoundation                      0x032f1846 CFRunLoopRunSpecific + 470
    16  CoreFoundation                      0x032f165b CFRunLoopRunInMode + 123
    17  GraphicsServices                    0x04a71664 GSEventRunModal + 192
    18  GraphicsServices                    0x04a714a1 GSEventRun + 104
    19  UIKit                               0x00e64eb9 UIApplicationMain + 160
    20  SignMeIn                            0x000534f2 main + 178
    21  libdyld.dylib                       0x040aaa25 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

My Meeting class has a speaker attribute of type Speaker *, and everything in the .m has @dynamic statements which should create the getter/setters.

Here's the code:

+ (void) addSpeakerWithDictionary: (NSDictionary *) speakerDict forMeeting: (Meeting *) aMeeting
{
    int speakerID = [speakerDict[@"id"] intValue];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"identification = %d AND %@ IN meeting", speakerID, aMeeting];
    NSArray *speakersArray = [CoreDataManager fetchObjects:@"Speaker" withSortDescriptors:nil andPredicate:predicate];

    if (speakersArray.count == 0)
    {
        Speaker *speaker = [NSEntityDescription insertNewObjectForEntityForName:@"Speaker" inManagedObjectContext:[CoreDataManager managedObjectContext]];

        speaker.degree =         speakerDict[@"degree"];
        speaker.firstName =      speakerDict[@"firstName"];
        speaker.identification = @(speakerID);
        speaker.lastName =       speakerDict[@"lastName"];
        speaker.preTitle =       speakerDict[@"preTitle"];
        speaker.version =        speakerDict[@"version"];

        aMeeting.speaker = speaker;

    }

Any help is greatly appreciated. Thanks!

Edit: Here's the calling method(s):

+ (void) insertMeetingsFromArray: (NSArray *) meetingsArray
{
    for (NSDictionary *dict in meetingsArray) 
    {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"identification = %d AND user = %@", [dict[@"id"] intValue], SessionManagerInstance.loggedUser];
        NSArray *meetArray = [CoreDataManager fetchObjects:@"Meeting" withSortDescriptors:nil andPredicate:predicate];

        if (meetArray.count)
        {
            Meeting *meeting = meetArray[0];
            [CoreDataManager addSpeakerWithDictionary:dict[@"speaker"] forMeeting:meeting];
        }
        else
            [CoreDataManager insertMeetingWithDictionary:dict];
    }

    [CoreDataManager saveContext];
}

And

+ (void) insertMeetingWithDictionary: (NSDictionary *) dict
{
//    NSLog(@"dict: %@", dict);
    Meeting *meeting = [NSEntityDescription insertNewObjectForEntityForName:@"Meeting" inManagedObjectContext:[CoreDataManager managedObjectContext]];

    meeting.brand =          dict[@"brand"];
    meeting.category =       dict[@"category"];
    meeting.city =           dict[@"city"];
    meeting.closed =         @([dict[@"closed"] boolValue]);
    meeting.date =           [Utilities dateFromDateTime:dict[@"date"]];
    meeting.dateString =     dict[@"dateString"];
    meeting.identification = @([dict[@"id"] intValue]);
    meeting.initiative =     dict[@"initiative"];
    meeting.location =       dict[@"location"];
    meeting.notes =          dict[@"notes"];
    meeting.state =          dict[@"state"];
    meeting.timeZone =       dict[@"timeZone"];
    meeting.title =          dict[@"title"];
    meeting.type =           dict[@"type"];

    [meeting setUser:SessionManagerInstance.loggedUser];

    [CoreDataManager addOrInsertRepWithDictionary:dict[@"rep"] forMeeting:meeting];
    [CoreDataManager addSpeakerWithDictionary:dict[@"speaker"] forMeeting:meeting];
    [CoreDataManager insertGroupsFromArray:dict[@"questiongroups"] forMeeting:meeting];

}

Updated with classes:

Meeting.h (using @dynamic in .m)

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

@class Attendee, Group, Rep, Speaker, User;

@interface Meeting : NSManagedObject

@property (nonatomic, retain) NSString * brand;
@property (nonatomic, retain) NSString * category;
@property (nonatomic, retain) NSString * city;
@property (nonatomic, retain) NSNumber * closed;
@property (nonatomic, retain) NSDate * date;
@property (nonatomic, retain) NSString * dateString;
@property (nonatomic, retain) NSNumber * identification;
@property (nonatomic, retain) NSString * initiative;
@property (nonatomic, retain) NSString * location;
@property (nonatomic, retain) NSNumber * needsToBeSubmitted;
@property (nonatomic, retain) NSString * notes;
@property (nonatomic, retain) NSString * state;
@property (nonatomic, retain) NSString * timeZone;
@property (nonatomic, retain) NSString * title;
@property (nonatomic, retain) NSString * transactionId;
@property (nonatomic, retain) NSString * type;
@property (nonatomic, retain) NSSet *attendees;
@property (nonatomic, retain) NSSet *groups;
@property (nonatomic, retain) Rep *rep;
@property (nonatomic, retain) Speaker *speaker;
@property (nonatomic, retain) User *user;
@end

@interface Meeting (CoreDataGeneratedAccessors)

- (void)addAttendeesObject:(Attendee *)value;
- (void)removeAttendeesObject:(Attendee *)value;
- (void)addAttendees:(NSSet *)values;
- (void)removeAttendees:(NSSet *)values;
- (void)addGroupsObject:(Group *)value;
- (void)removeGroupsObject:(Group *)value;
- (void)addGroups:(NSSet *)values;
- (void)removeGroups:(NSSet *)values;

@end

Speaker.h (using @dynamic in .m)

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


@interface Speaker : NSManagedObject

@property (nonatomic, retain) NSString * degree;
@property (nonatomic, retain) NSString * firstName;
@property (nonatomic, retain) NSNumber * identification;
@property (nonatomic, retain) NSString * lastName;
@property (nonatomic, retain) NSString * preTitle;
@property (nonatomic, retain) NSString * version;
@property (nonatomic, retain) NSSet *meeting;
@end

@interface Speaker (CoreDataGeneratedAccessors)

- (void)addMeetingObject:(NSManagedObject *)value;
- (void)removeMeetingObject:(NSManagedObject *)value;
- (void)addMeeting:(NSSet *)values;
- (void)removeMeeting:(NSSet *)values;

@end

Upvotes: 1

Views: 1126

Answers (2)

Mochi
Mochi

Reputation: 1117

Make sure current Core Data model have the right property.

I ran into a similar problem with Core Data where I was getting an unrecognized selector with a setter method error. I accidentally renamed the attribute in my current Core Data model a different name than my Core Data class.

Upvotes: 0

Tom Harrington
Tom Harrington

Reputation: 70946

The mention of NSKnownKeysDictionary1 almost certainly means that this line:

[CoreDataManager fetchObjects:@"Meeting" withSortDescriptors:nil andPredicate:predicate];

...is doing a fetch request where the result type is NSDictionaryResultType. That would mean that meetArray[0] is a dictionary, not a managed object. It won't have a setSpeaker method, which causes the error you're seeing.

You could change the fetch request to return managed objects, unless you need them to be dictionaries for some reason. But you can't use dictionaries like this.

Upvotes: 2

Related Questions