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 archive(cnGroup: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 unarchive(dataOfCNGroup: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(...) {...}

Hi @brower ,
I will have to download an older version of Xcode to try this on 12.4, However I feel that the API has changed and though all references talk about secure coding, that has made some changes. I need some time to try this and come back to you.

At work, I have many clients and where I can influence, we have a minimum of iOS15 and where we cannot influence much, it is n-2 which is 15-2 = 13. While we can try to resolve this issue or find out the problem, if you can get the project to a minimum of iOS13 or higher, it might be more efficient in a lot of ways.

will come back to you,

Jayant