I’m coding Swift for iOS 11, and in some context (described in part 2) I end up with a variable of type String. However, when examining the variable in Xcode’s debugger the type is shown as _PFEncodedString (which I have read elsewhere is an internal subclass of String). For some reason (described below, but not directly related to the first part of my question) I want to transform the _PFEncodedString variable to a plain String variable. The only way I’ve found to do that is as follows:
var attributeName : String
// ... attributeName is assigned a value and ends up being _PFEncodedString
let data = attributeName.data(using: String.Encoding.utf8)!
let plainName = String(data: data, encoding: String.Encoding.utf8)! // this is type String not _PFEncodedString
The first part of my question is: Is this conversion safe or is there is simpler or better way to do it?
Part 2. For the second part of my question I will first describe the context where the above becomes an issue. I’m using Core Data and want to export attribute names (and values) to JSON. Using reflection I can find Core Data entity names and find the attribute names that should be exported to JSON. The problem is that when I use JSONEncoder with this data, the generated JSON contains Chinese characters whereas the Core Data model attribute names do not. I have found that JSONEncoder produces partly Chinese output when Strings in the exported object is of type _PFEncodedString, but works fine when handling "plain" String types. Therefore the first part of my questions.
Here is code that illustrates the problem, boiled down to a near minimum. QPTVideo is a subclass of NSManagedObject with two attributes ‘qaUUID’ and ‘thumbnailData’.
// First define a struct to be used with JSONEncoder
struct AttributeForJSON : Codable {
var name : String
}
let entityDescription = QPTVideo.entity()
let attributes = entityDescription.attributesByName // this is an array of (key: String, value: NSAttributeDescription).
var allAttributes : [AttributeForJSON] = [] // this will be an array of all the attribute names for export to JSON.
for attribute in attributes {
let attributeName = attribute.key // NOTE: debugger shows this as: attributeName String class name = _PFEncodedString
let aj = AttributeForJSON(name: attributeName)
print(aj.name) // this works just fine, printing “qaUUID” or “thumbnailData”
allAttributes.append(aj) // when exported, the attribute names look nothing like they should, containing Chinese characters.
// now use the work-around from first part of my question:
let data = attributeName.data(using: String.Encoding.utf8)!
let plainName = String(data: data, encoding: String.Encoding.utf8)! // NOTE: debugger shows this as: plainName String "thumbnailData"
let ajplain = AttributeForJSON(name: plainName)
allAttributes.append(ajplain) // when exported, the attribute names are correct.
}
// the rest is just use of JSONEncoder to generate the JSON
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
do {
let data = try encoder.encode(allAttributes)
try data.write(to: URL(fileURLWithPath: “/Users/someone/so.json"), options: Data.WritingOptions.atomic)
} catch {
print(error.localizedDescription)
}
The exported JSON looks like this (where I would have expected both of the first two name
values to be "qaUUID", and the next two to be "thumbnailData"):
[
{
"name" : "慱啕䑉\u0000戨্"
},
{
"name" : "qaUUID"
},
{
"name" : "桴浵湢楡䑬瑡a\u0000戨্\u0001\u0000\u0000"
},
{
"name" : "thumbnailData"
}
]
So, my here question is: Why do I get Chinese characters? What am I doing wrong in how I use the Core Data reflection API and/or JSONEncoder? How do I do this without resorting to the work-around from the first part of my question?