我新创建的Swift解码器(对于某些旧的OBJ-C持续存在的UserDefaults数据)正在为某些特定现有和存储的字符串字段而获取零

发布于 2025-02-12 20:33:42 字数 3817 浏览 1 评论 0原文

上下文:

我被赋予了从我们团队一段时间以前创建的某个应用程序的旧版本中创建持久的UserDefaults数据进口商的任务。 该应用程序是使用Objectivec和某种“旧学校数据建模”(不是由我甚至当前团队)创建的。 新应用程序是一个可预期的Swiftui Swift Modern应用程序,但是当启动时,它仍需要检测到可能的旧数据,然后能够导入它。

问题:

在解析/解码旧的UserDefaults时,此(可选的)犯罪现场将其生存为存储在上述用户默认违规中的BPLIST。尽管据称该领域似乎是一个NSMUTABLESTRING,但在尝试解码时总是会给零。 我已经“逆向工程”的BPLIST文件的部分存储了所有这些数据字段,并且我获得了此(字段重命名的)对象:

编辑: 下面的下一个数据是从内存中的“压缩” BPLIST对象转换到数据上,然后使用plutil -p转换到ASCII上 在使用Xcode调试器断点时,此内存捕获的时刻是在“ Li”崩溃/无线线之前的:

2 => {
  "_de" => <CFKeyedArchiverUID 0x600001b21ae0 [0x1e76f0000]>{value = 4}
  "_or" => <CFKeyedArchiverUID 0x600001b21b20 [0x1e76f0000]>{value = 3}
  "$class" => <CFKeyedArchiverUID 0x600001b21b60 [0x1e76f0000]>{value = 9}
  "fa" => <CFKeyedArchiverUID 0x600001b21b40 [0x1e76f0000]>{value = 5}
  "li" => <CFKeyedArchiverUID 0x600001b21b80 [0x1e76f0000]>{value = 6}
  "tr" => <CFKeyedArchiverUID 0x600001b21b00 [0x1e76f0000]>{value = 8}
}


4 => "Ca"           // Non crashing String

3 => "AT"          // Again non crashing String

9 => {
  "$classes" => [
    0 => "IVO"
    1 => "GenericVO"
    2 => "OFValueObject"
    3 => "NSObject"
  ]
  "$classname" => "IVO"
}

5 => 1         // Numeric value, it loads ok.

6 => {
  "$class" => <CFKeyedArchiverUID 0x600001b21ba0 [0x1e76f0000]>{value = 7}
  "NS.string" => "S17"   // This is the unobtainable field
}

7 => {
  "$classes" => [
    0 => "NSMutableString"
    1 => "NSString"
    2 => "NSObject"
  ]
  "$classname" => "NSMutableString"
}

8 => "S2"           // Loads perfectly

此IVO类是在旧的目标C代码中定义的,其中包括这些成员(除其他内容):

class IVO: NSObject, NSCoding, NSSecureCoding{


    @property (nonatomic, strong) NSString *_or;
    @property (nonatomic, strong) NSString *_de;
    @property (nonatomic, strong) NSNumber *fa;
    @property (nonatomic, strong) NSString *li;
    @property (nonatomic, strong) NSString *tr;

    static var supportsSecureCoding: Bool = true

我不知道或访问做出导致阶级命名/结构的决策。

我的新目标Swift IVO类具有这些成员(试图模仿原始成员):

let _or: String
let _de: String
let fa: Int
let li: String
let tr: String

此新重新创建的类中的解码器代码也是这样的:

required init?(coder: NSCoder) {

    _or = coder.decodeObject(forKey: "_or") as! String
    _de = coder.decodeObject(forKey: "_de") as! String
    fa = coder.decodeObject(forKey: "fa") as! Int

    tr = coder.decodeObject(forKey: "tr") as! String

    // Many diferent types of cast have been tried here
    // Just asking with no-cast returns a nil into l

    if let l = (coder.decodeObject(forKey: "li") as? NSMutableString)   
    {
        li = l as String
    }
    else
    {
        // I'm ENTERING THROUGH THIS BRANCH... the "if let" is to avoid the crash
        li = ""
    }
    
    // I wish I could use something as simple as this
    //li = coder.decodeObject(forKey: "li") as! String // or NSMutableString (?)

    super.init()
    
}

编辑:在这里:在这里,我将调用IVO类的代码片段放置来解码数据:

var encodedData = UserDefaults.standard.object(forKey: "Fa")
NSKeyedUnarchiver.setClass(MY_PROJECT_NAME.IVO.self, forClassName: "IVO")
var arrayObjects = try NSKeyedUnarchiver.unarchivedArrayOfObjects(ofClass: IVO.self, from: encodedData as! Data)

注意:

我更改了tr对象读取顺序只是为了查看它是否有要做的事情,而且显然没有,tr字段正确地读取。

问题:

我应该如何检查更多内容以读取当前返回零的“ li”属性? (因此崩溃/未获取预期的存储数据?)

注意:

在上面发布的“爆炸” BPLIST中,我实际上可以看到这个“ li”属性似乎不是正常字符串,因为兄弟姐妹,但“ nsmutableString”(其类别定义以Node'7'延迟了一步)。是否有一种特别的方式读取以这种“重新定义/nsmutableString” Bplist节点读取此字符串信息?

这是一个复杂的问题,我可能正在编辑一些详细信息/错别字,甚至在有人要求我这样做的情况下添加更多信息。

所有的帮助将受到欢迎,谢谢。

Context:

I've been given the task of creating a persisted UserDefaults data importer from an old version of some app our team created some time ago.
That app was created using ObjectiveC, and some kind of "old school data modeling" (not by me or even the current team).
The new app is an expectably shiny SwiftUI Swift modern application, but still, when at boot time it needs to detect this possible old persisted data and then being able to import it.

Problem:

When parsing/decoding the old UserDefaults, this (optional) offending field lives into some bplist stored in said UserDefaults. While allegedly this field seems to be a NSMutableString, it always gives nil when tried to be decoded.
I've "reverse engineered" parts of the bplist file where all these data fields are stored, and I have obtained this (field renamed) object:

EDIT:
The next data below is the transformation from "compressed" bplist object in memory onto Data and then onto ASCII using plutil -p
The moment of this memory capture is RIGHT before the "li" crashing/nil line while using a Xcode debugger breakpoint:

2 => {
  "_de" => <CFKeyedArchiverUID 0x600001b21ae0 [0x1e76f0000]>{value = 4}
  "_or" => <CFKeyedArchiverUID 0x600001b21b20 [0x1e76f0000]>{value = 3}
  "$class" => <CFKeyedArchiverUID 0x600001b21b60 [0x1e76f0000]>{value = 9}
  "fa" => <CFKeyedArchiverUID 0x600001b21b40 [0x1e76f0000]>{value = 5}
  "li" => <CFKeyedArchiverUID 0x600001b21b80 [0x1e76f0000]>{value = 6}
  "tr" => <CFKeyedArchiverUID 0x600001b21b00 [0x1e76f0000]>{value = 8}
}


4 => "Ca"           // Non crashing String

3 => "AT"          // Again non crashing String

9 => {
  "$classes" => [
    0 => "IVO"
    1 => "GenericVO"
    2 => "OFValueObject"
    3 => "NSObject"
  ]
  "$classname" => "IVO"
}

5 => 1         // Numeric value, it loads ok.

6 => {
  "$class" => <CFKeyedArchiverUID 0x600001b21ba0 [0x1e76f0000]>{value = 7}
  "NS.string" => "S17"   // This is the unobtainable field
}

7 => {
  "$classes" => [
    0 => "NSMutableString"
    1 => "NSString"
    2 => "NSObject"
  ]
  "$classname" => "NSMutableString"
}

8 => "S2"           // Loads perfectly

This IVO Class is defined in the old objective C code with these members (among other stuff):

class IVO: NSObject, NSCoding, NSSecureCoding{


    @property (nonatomic, strong) NSString *_or;
    @property (nonatomic, strong) NSString *_de;
    @property (nonatomic, strong) NSNumber *fa;
    @property (nonatomic, strong) NSString *li;
    @property (nonatomic, strong) NSString *tr;

    static var supportsSecureCoding: Bool = true

I have no idea or access to the decisions that lead to the beforementioned class naming/structure.

My new destination swift IVO class has these members (which try to mimic the original ones):

let _or: String
let _de: String
let fa: Int
let li: String
let tr: String

Also the decoder code inside this new recreated class is this one:

required init?(coder: NSCoder) {

    _or = coder.decodeObject(forKey: "_or") as! String
    _de = coder.decodeObject(forKey: "_de") as! String
    fa = coder.decodeObject(forKey: "fa") as! Int

    tr = coder.decodeObject(forKey: "tr") as! String

    // Many diferent types of cast have been tried here
    // Just asking with no-cast returns a nil into l

    if let l = (coder.decodeObject(forKey: "li") as? NSMutableString)   
    {
        li = l as String
    }
    else
    {
        // I'm ENTERING THROUGH THIS BRANCH... the "if let" is to avoid the crash
        li = ""
    }
    
    // I wish I could use something as simple as this
    //li = coder.decodeObject(forKey: "li") as! String // or NSMutableString (?)

    super.init()
    
}

EDIT: Here I put the snippet of code that calls the IVO class to decode data:

var encodedData = UserDefaults.standard.object(forKey: "Fa")
NSKeyedUnarchiver.setClass(MY_PROJECT_NAME.IVO.self, forClassName: "IVO")
var arrayObjects = try NSKeyedUnarchiver.unarchivedArrayOfObjects(ofClass: IVO.self, from: encodedData as! Data)

Note:

I changed tr object reading order just to see if it had something to do, and apparently not, the tr field is properly read.

QUESTION:

How should I check more things to be able to read the "li" attribute that is currently returning nil? (and thus Crashing/not getting the expected stored data ?)

Note:

In the "exploded" bplist I posted above I can actually see how this "li" attribute seems not to be a normal String as its siblings, but a "NSMutableString" (with its class definition deferred one step with node '7'). Is there a particulary way to read this String info living in this kind of "redefined/NSMutableString" bplist node ?

It's a complex question and I might be editing some of the details/typos, or even adding more info if someone asks me to do it.

All help will be welcome, thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文