I get a code-time yellow warning message in Xcode that says:
'unarchiveObject(with:)' was deprecated in iOS 12.0: Use +unarchivedObjectOfClass:fromData:error: instead
... when I use the following code:
let oldUbiquityIdentityToken = NSKeyedUnarchiver
.unarchiveObject(with: oldDataUbiquityIdentityToken!)
When I change to unarchivedObject(ofClass:from:) I get 2 code-time red error messages before I even fill in the arguments:
'NSCoding' cannot be used as a type conforming to protocol 'NSCoding' because 'NSCoding' has static requirements
Static method 'unarchivedObject(ofClass:from:)' requires that 'NSCoding' inherit from 'NSObject'
Why am I getting these error messages?
I change the code to:
let defaultFileManager: FileManager = FileManager.default
let standardUserDefaults = UserDefaults.standard
let ubiquityIdentityToken = defaultFileManager.ubiquityIdentityToken
let oldDataUbiquityIdentityToken = standardUserDefaults.data(forKey: UserDefaultsKeys.ubiquityIdentityToken)
do {
let dataUbiquityIdentityToken: Data = try NSKeyedArchiver.archivedData(withRootObject: ubiquityIdentityToken!, requiringSecureCoding: false) // error messages appear here
standardUserDefaults.set(dataUbiquityIdentityToken, forKey: UserDefaultsKeys.ubiquityIdentityToken)
let oldUbiquityIdentityToken = try NSKeyedUnarchiver.unarchivedObject(ofClass: (NSCoding & NSCopying & NSObjectProtocol).self, from: oldDataUbiquityIdentityToken!)
} catch {
print(error)
}
Here are the red code-time errors that appear on the line I mark with comments in the code:
'NSCoding & NSCopying & NSObjectProtocol' cannot be used as a type conforming to protocol 'NSCoding' because 'NSCoding' has static requirements
Static method 'unarchivedObject(ofClass:from:)' requires that 'NSCoding & NSCopying & NSObjectProtocol' inherit from 'NSObject'
I get the argument I put in for the 'forClass' parameter from the declaration of FileManager.ubiquityIdentityToken in Apple's documentation, which says:
@NSCopying var ubiquityIdentityToken: (NSCoding & NSCopying & NSObjectProtocol)? { get }
What threw me off at the beginning is the fact that the errors appear before I even put in the arguments in the placeholders.
Update on July 8, 2022:
Now I get the following code-time error messages when I use the following code:
Static method 'unarchivedObject(ofClass:from:)' requires that 'Data' conform to 'NSCoding'
Static method 'unarchivedObject(ofClass:from:)' requires that 'Data' inherit from 'NSObject'
let oldUbiquityIdentityToken = NSKeyedUnarchiver.unarchivedObject(ofClass: Data.self, from: oldDataUbiquityIdentityToken!)
I didn't get that first error message before, but I did get that second message before.
When I execute the following code, I get the following in debug window:
print(type(of: FileManager.default.ubiquityIdentityToken))
print(type(of: FileManager.default.ubiquityIdentityToken!))
Optional<NSCoding & NSCopying & NSObject> _NSInlineData
The NSKeyedUnarchiver.unarchivedObject(ofClass:from:)
method is expecting the decoded object to conform to NSCoding
or NSSecureCoding
, which are class-only protocols. Data
is a struct
that does not and could not conform to both, instead, you could use NSData
which directly bridges to Data
as such:
let defaultFileManager = FileManager.default
let standardUserDefaults = UserDefaults.standard
let ubiquityIdentityToken = defaultFileManager.ubiquityIdentityToken
// archiving and setting user defaults
do {
let tokenData = try NSKeyedArchiver.archivedData(withRootObject: ubiquityIdentityToken!,
requiringSecureCoding: false)
standardUserDefaults.set(tokenData, forKey: UserDefaultsKeys.ubiquityIdentityToken)
} catch {
print(error)
}
// unarchiving from user defaults
let oldDataUbiquityIdentityToken = standardUserDefaults.data(forKey: UserDefaultsKeys.ubiquityIdentityToken)!
do {
if let oldTokenData = try NSKeyedUnarchiver.unarchivedObject(ofClass: NSData.self,
from: oldDataUbiquityIdentityToken) {
print(ubiquityIdentityToken!.isEqual(to: oldTokenData)) // prints 'true'
print(oldTokenData) // {length = ..., bytes = ...}
}
} catch {
print(error)
}