Backward compatibility of NSKeyedUnarchiver class of Apple Foundations for iOS

I'm getting errors when I use NSKeyedArchiver and NSKeyedUnarchiver that works with iOS 15.5 but not with iOS 12.4 nor iOS 12.5.5. I have tried combinations of using devices and simulators. The error message appears in the Xcode debug window when the catch scope handles an error that occurs when the following statement executes:

    try NSKeyedUnarchiver.unarchivedObject(ofClass: CNGroup.self, from: dataToUnarchive)

Here is what prints in the Xcode debug window for Error.localizedDescription:

The data couldn’t be read because it isn’t in the correct format.

Here is what prints in the Xcode debug window when only the Error object is put in the print statement parentheses:

Error Domain=NSCocoaErrorDomain Code=4864 "*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x62, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4)" UserInfo={NSDebugDescription=*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x62, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4)}

I found an answer to a similar question like this in Apple Developer Forums which had to do with NSCoder that indicated that the older iOS expects the Data object not to use secure coding, my code as this post concerns is not using secure coding. There are stackoverflow questions that deal with similar questions to mine, but they are very old and they deal with different facets of NSCoder.

The following are the respective function definitions for archive(cnGroup:completionHandler:) and unarchive(dataOfCNGroup:completionHandler) that I use.

Definition for unarchive(dataOfCNGroup:completionHandler)

    func archive(cnGroup: CNGroup, completionHandler: @escaping (Result<Data, Error>)->Void) {
        
        do {
            
            if #available(iOS 11.0, *) {
                let data: Data = try NSKeyedArchiver.archivedData(withRootObject: cnGroup, requiringSecureCoding: false)
                completionHandler(.success(data))
            } else {
                let data: Data = NSKeyedArchiver.archivedData(withRootObject: cnGroup)
                completionHandler(.success(data))
            }
            
            
        } catch {
            
            completionHandler(.failure(error))
            
        }
        
    } // func archive(...) {...}

Definition for archive(cnGroup:completionHandler:)

    func unarchive(dataOfCNGroup dataToUnarchive: Data, completionHandler: @escaping (Result<CNGroup, Error>)->Void) {
        
        print("func unarchive(dataOfCNGroup dataToUnarchive: Data, completionHandler: @escaping (Result<CNGroup, Error>)->Void)")
        
        do {
            
            if let unwrappedUnarchivedCNGroup: CNGroup = try NSKeyedUnarchiver.unarchivedObject(ofClass: CNGroup.self, from: dataToUnarchive) {
                
                completionHandler(.success(unwrappedUnarchivedCNGroup))
                
            } else {
                
                let nsError = NSError(domain: "func unarchive(dataOfCNGroup dataToUnarchive: Data, completionHandler: @escaping (Result<CNGroup, Error>?)->Void)", code: #line, userInfo: nil)
                
                let error: Error = nsError
                
                completionHandler(.failure(error))
                
                return
            }

        } catch {
            
            print("catch error in unarchive(dataOfCNGroup:_:) on line \(#line)")
            print("\(error.localizedDescription)")
            
            completionHandler(.failure(error))
            
        }
        
    } // func unarchive(...) {...}

I'm getting errors when I use NSKeyedArchiver and NSKeyedUnarchiver that works with iOS 15.5 but not with iOS 12.4 nor iOS 12.5.5.

I want to clarify what you’re seeing here. My reading of your post is that:

  • If you run your archiving and unarchiving code on iOS 15.5, it works.

  • If you run the same code on iOS 12, it fails.

  • At no point are you trying to move an archive between iOS 12 and iOS 15, or vice versa.

Is that correct?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Backward compatibility of NSKeyedUnarchiver class of Apple Foundations for iOS
 
 
Q