I am trying to implement NSSecureCoding but am getting some problems my code is this. a class called WrapperClass:
public class WrapperClass:NSObject, NSCoding, NSSecureCoding {
public static var supportsSecureCoding: Bool = true
var attributedStrings = [TextDocumentClass]()
init(pAttributedStrings:[TextDocumentClass]) {
self.attributedStrings = pAttributedStrings
}
required public init?(coder aDecoder: NSCoder){
self.attributedStrings = aDecoder.decodeObject(of: [TextDocumentClass.self], forKey: "attributedStrings") as? [TextDocumentClass]
//return self
}
public func encode(with aCoder: NSCoder) {
aCoder.encode(attributedStrings,forKey:"attributedStrings")
}
}
when this code get run i get nil instead of array of TextDocumentClass and i don't now why, i have tried using the following classes in aDecoder.decodeObject ([TextDocumentClass.self], NSArray.self and TextDocumentClass.self] but they all give the same I have made my own ValueTransformer because i need to support some classes that i don't think is included with the default for NSSecureUnarchiveFromDataTransformer
@objc(MyTestClassValueTransformer)
final class MyClassValueTransformer: NSSecureUnarchiveFromDataTransformer {
static let name = NSValueTransformerName(rawValue: String(describing: MyClassValueTransformer.self))
public static func register() {
let transformer = MyClassValueTransformer()
ValueTransformer.setValueTransformer(transformer, forName: name)
}
override static var allowedTopLevelClasses: [AnyClass] {
return super.allowedTopLevelClasses + [WrapperClass.self, UIFont.self, NSObject.self, NSParagraphStyle.self]
}
override public class func transformedValueClass() -> AnyClass {
return WrapperClass.self
}
override public class func allowsReverseTransformation() -> Bool {
return true
}
override public func transformedValue(_ value: Any?) -> Any? {
guard let data = value as? Data else {
return nil
}
do {
let box = try NSKeyedUnarchiver.unarchivedObject(
ofClass: WrapperClass.self,
from: data
)
return box
} catch {
return nil
}
}
override public func reverseTransformedValue(_ value: Any?) -> Any? {
guard let box = value as? WrapperClass else {
return nil
}
do {
let data = try NSKeyedArchiver.archivedData(
withRootObject: box,
requiringSecureCoding: true
)
return data
} catch {
return nil
}
}
}
The class TextDocumentClass contains the following variables NSAttributedString, String, Bool and Int
public class TextDocumentClass:NSObject, NSCoding, NSSecureCoding {
public static var supportsSecureCoding: Bool = true
var attributedText: NSAttributedString!
var uuid:String!
var isDeleted:Bool!
var isChanged:Bool!
var prevPageUUID:String!
var nextPageUUID:String!
var order:Int!
var lastUpdatedDate:String!
var isPDF: Bool!
var pdfURL: String!
var pdfPageNumber: Int!
init (pAttributedText:NSAttributedString, pUUID:String, pPrevPageUUID:String, pNextPageUID:String, pOrder:Int, pIsDeleted: Bool, pIsChanged: Bool, pLastUpdatedDate: String, isPDF: Bool = false, pdfURL: String = "", pdfPageNumber: Int = -1) {
self.attributedText = pAttributedText
self.uuid = pUUID
self.isDeleted = pIsDeleted
self.isChanged = pIsChanged
self.prevPageUUID = pPrevPageUUID
self.nextPageUUID = pNextPageUID
self.order = pOrder
self.lastUpdatedDate = pLastUpdatedDate
self.isPDF = isPDF
self.pdfURL = pdfURL
self.pdfPageNumber = pdfPageNumber
}
required public init?(coder aDecoder: NSCoder){
self.attributedText = (aDecoder.decodeObject(of: NSAttributedString.self, forKey: "attributedText"))!
self.prevPageUUID = (aDecoder.decodeObject(of: NSString.self, forKey: "prevPageUUID") as? String)!
self.nextPageUUID = (aDecoder.decodeObject(of: NSString.self, forKey: "nextPageUUID") as? String)!
self.uuid = (aDecoder.decodeObject(of: NSString.self, forKey: "uuid") as? String)!
self.isChanged = (aDecoder.decodeObject(of: NSNumber.self, forKey: "isChanged")?.boolValue)!
self.isDeleted = (aDecoder.decodeObject(of: NSNumber.self, forKey: "isDeleted")?.boolValue)!
self.order = (aDecoder.decodeObject(of: NSNumber.self, forKey: "order")?.intValue)!
self.lastUpdatedDate = (aDecoder.decodeObject(of: NSString.self, forKey: "lastUpdatedDate") as? String)!
self.isPDF = aDecoder.decodeObject(of: NSNumber.self, forKey: "isPDF")?.boolValue ?? false
self.pdfURL = (aDecoder.decodeObject(of: NSString.self, forKey: "pdfURL") as? String ?? "")
self.pdfPageNumber = aDecoder.decodeObject(of: NSNumber.self, forKey: "PDFpageNumber")?.intValue ?? -1
}
public func encode(with aCoder: NSCoder) {
aCoder.encode(attributedText,forKey:"attributedText")
aCoder.encode(prevPageUUID,forKey:"prevPageUUID")
aCoder.encode(nextPageUUID,forKey:"nextPageUUID")
aCoder.encode(uuid,forKey:"uuid")
aCoder.encode(isChanged,forKey:"isChanged")
aCoder.encode(isDeleted,forKey:"isDeleted")
aCoder.encode(order,forKey:"order")
aCoder.encode(lastUpdatedDate,forKey:"lastUpdatedDate")
aCoder.encode(isPDF, forKey: "isPDF")
aCoder.encode(pdfURL, forKey: "pdfURL")
aCoder.encode(pdfPageNumber, forKey: "PDFpageNumber")
}
override public init() {
self.attributedText = NSAttributedString()
self.uuid = ""
self.isDeleted = false
self.isChanged = false
self.prevPageUUID = ""
self.nextPageUUID = ""
self.order = -1
self.lastUpdatedDate = ""
self.isPDF = false
self.pdfURL = ""
self.pdfPageNumber = -1
}
}
A little extra information not sure if it helps, i figure out how to get a error about why its nil
//this code line
let temp = try aDecoder.decodeTopLevelObject(of: [BaselineClass.self], forKey: "attributedStrings")
//gives this print in console
Allowed classes are:
{(
"'demo.BaselineClass' (0x100f6fc40) [/private/var/containers/Bundle/Application/EF7BF8EB-A98B-4B52-AE8F-1FB05F31ECC3/demo.app]"
)}" UserInfo={NSDebugDescription=value for key 'attributedStrings' was of unexpected class 'NSArray' (0x1fc4b89e0) [/System/Library/Frameworks/CoreFoundation.framework].
Allowed classes are:
{(
"'demo.BaselineClass' (0x100f6fc40) [/private/var/containers/Bundle/Application/EF7BF8EB-A98B-4B52-AE8F-1FB05F31ECC3/demo.app]"
)}}
//if i change the code line to use NSArray.self so it looks like this
let temp = try aDecoder.decodeTopLevelObject(of: NSArray.self, forKey: "attributedStrings")
//i get this in console instead
Allowed classes are:
{(
"'NSArray' (0x1fc4b89e0) [/System/Library/Frameworks/CoreFoundation.framework]"
)}" UserInfo={NSDebugDescription=value for key 'NS.objects' was of unexpected class 'demo.BaselineClass' (0x103363c40) [/private/var/containers/Bundle/Application/1E080145-14D1-4D03-9520-E87C39B8F2C7/demo.app].
Allowed classes are:
{(
"'NSArray' (0x1fc4b89e0) [/System/Library/Frameworks/CoreFoundation.framework]"
)}}
Any help in solving this is appreciated thanks.
After communication back and forth with Apple the following solved my problem. When decoding the array of classes se code
it should be changed to this.
Then i also had some other small bug in my TextDocumentClass public initialiser where instead of decodeObject for bool and int i should use decodeBool and decodeInt32.