2
votes

I have two different applications (one written in Objective-C, one in Swift) that share some data. I've decided to do the synchronization through iCloud. The items to be synced are packed in an array and then saved to a file. Everything works as expected, when syncing the Objective-C app, but I get the following error, when I try to download the file in the Swift app:

Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (Favourite) for key (NS.objects); the class may be defined in source code or a library that is not linked'

Here are both Favourite classes:

Objective C:

@interface Favourite : NSObject

@property(retain,nonatomic) NSString* mArtikeltext;
@property(retain,nonatomic) NSString* mRid;

-(instancetype) initWithObject:(NSMutableDictionary*) object;

@end

.m:

@implementation Favourite


-(instancetype) initWithObject:(NSMutableDictionary *)object{
    self = [super init];
    if(self){
        self.mArtikeltext = [object valueForKey:@"mArtikeltext"];
        self.mRid = [object valueForKey:@"mRid"];
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *) coder
{
    [coder encodeObject:self.mArtikeltext forKey:@"mArtikeltext"];
    [coder encodeObject:self.mRid forKey:@"mRid"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    if (self = [super init]) {
        self.mArtikeltext = (NSString *)[decoder decodeObjectForKey:@"mArtikeltext"];
        self.mRid = (NSString *)[decoder decodeObjectForKey:@"mRid"];
    }


    return self;
}

@end

Swift:

class Favourite: NSObject, NSCoding {

    var mArtikeltext: String = ""
    var mRid: String = ""

    init(object: [String: AnyObject]) throws {
        super.init()
        guard case let (text as String, rid as String) = (object["mArtikelText"], object["mRid"]) else {
            throw JSONResponseError.NilResponseValue
        }
        self.mArtikeltext = text
        self.mRid = rid
    }

    required init?(coder aDecoder: NSCoder) {
        super.init()
        self.mArtikeltext = aDecoder.decodeObjectForKey("mArtikeltext") as! String
        self.mRid = aDecoder.decodeObjectForKey("mRid") as! String
    }

    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(self.mArtikeltext, forKey: "mArtikeltext")
        aCoder.encodeObject(self.mRid, forKey: "mRid")
    }
}

This is how I unarchive the data in Swift:

let cloudFavs: [Favourite] = NSKeyedUnarchiver.unarchiveObjectWithData(data) as! [Favourite]

and in Objective-C:

NSArray *favs = [NSKeyedUnarchiver unarchiveObjectWithData:data];

Any ideas how to fix the error ?

1

1 Answers

0
votes

Ok, after some more digging, I found the answer. I had to declare the Objective-C class name in the swift class, like this:

@objc(Favourite)
class Favourite: NSObject, NSCoding {
    // and so on..

This fixed the issue.