What is wrong with the implementation of the NSCoding protocol in Swift

I thought I would be careful and try Swift in an existing Obj-C project by translating one class. And small, simple at that. Oh dear.

Transliterating the original obj-c into Swift should be easy, and it seemed so. Unfortunately, although the encoder in persistent storage works, it crashes with an EXC_BREAKPOINT error in the first line of the initializer.

IF (and caps intentionally) NSCoding / Swift gives the same persistent content as NSCoding / ObjC, then my entire version of obj-c should be able to read what is encoded by Swift and vice versa. This is not the case, and my perfectly working version of obj-c crashes when trying to read persistent storage from the Swift version. Of course, if NSCoding is done correctly, should it generate something in one that reads in the other? Otherwise, should there be separate protocols NSCodingSwift and NSCodingObjC?

So, to summarize, I can read / write in obj-c. I cannot write / obj -c and read / fast, and I can write / quickly read / obj -c, and I cannot read / write in swift.

Here are two versions:

let keyBeaconItemNameKey = "name" let keyBeaconItemUUIDKey = "uuid" let keyBeaconItemMajorValueKey = "major" let keyBeaconItemMinorValueKey = "minor" import UIKit import CoreLocation class SMBeaconItem : NSObject, NSCoding { var name : String! var uuid : NSUUID! var major : NSNumber! var minor : NSNumber! init(newName : String, newUUID : NSUUID, newMajor : NSNumber, newMinor : NSNumber ) { name = newName uuid = newUUID major = newMajor minor = newMinor } init( coder decoder : NSCoder!) { name = decoder.decodeObjectForKey(keyBeaconItemNameKey) as String uuid = decoder.decodeObjectForKey(keyBeaconItemUUIDKey) as NSUUID major = decoder.decodeObjectForKey(keyBeaconItemMajorValueKey) as NSNumber minor = decoder.decodeObjectForKey(keyBeaconItemMinorValueKey) as NSNumber } func encodeWithCoder( encoder: NSCoder!) { encoder.encodeObject(name, forKey:keyBeaconItemNameKey) encoder.encodeObject(uuid, forKey:keyBeaconItemUUIDKey) encoder.encodeObject(major, forKey:keyBeaconItemMajorValueKey) encoder.encodeObject(minor, forKey:keyBeaconItemMinorValueKey) } } 

And the working original:

 @implementation SMBeaconItem - (instancetype)initWithName:(NSString *)name uuid:(NSUUID *)uuid major:(CLBeaconMajorValue)major minor:(CLBeaconMinorValue)minor { self = [super init]; if (!self) { return nil; } _name = name; _uuid = uuid; _majorValue = major; _minorValue = minor; return self; } #pragma mark - Persistence - (instancetype)initWithCoder:(NSCoder *)aDecoder { self = [super init]; if (!self) { return nil; } _name = [aDecoder decodeObjectForKey:keyBeaconItemNameKey]; _uuid = [aDecoder decodeObjectForKey:keyBeaconItemUUIDKey]; _majorValue = [[aDecoder decodeObjectForKey:keyBeaconItemMajorValueKey] unsignedIntegerValue]; _minorValue = [[aDecoder decodeObjectForKey:keyBeaconItemMinorValueKey] unsignedIntegerValue]; return self; } - (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject:self.name forKey:keyBeaconItemNameKey]; [aCoder encodeObject:self.uuid forKey:keyBeaconItemUUIDKey]; [aCoder encodeObject:[NSNumber numberWithUnsignedInteger:self.majorValue] forKey:keyBeaconItemMajorValueKey]; [aCoder encodeObject:[NSNumber numberWithUnsignedInteger:self.minorValue] forKey:keyBeaconItemMinorValueKey]; } @end 

Thanks for any help you can give.

+7
objective-c swift
source share
1 answer

The only thing that stands out for me is that you use String instead of NSString as a type of name . In the beta releases Apple releases, String (oddly enough) is not a replacement for NSString by one. Namely, some methods are missing and require calling .bridgeToObjectiveC() to get the version of NSString . Using this type is likely to be consistent with what NSCoder expects, although this difference should not be the same.

I really have not tested this statement since I am not on my dev machine. But this is my gut instinct. Try it and see what happens! If nothing changes, try switching the order of the var settings and see if the problem is related to the name field or just the first line of the init function.

0
source share

All Articles