Browse Source

feat: 为了从 YYModel 过度到 Decodable,增加解析的兼容代码,TODO: YYModel 废弃后 revert

陈文艺 5 months ago
parent
commit
ee4ccf8902
2 changed files with 42 additions and 2 deletions
  1. 37 0
      YYKit/Model/NSObject+Decodable.swift
  2. 5 2
      YYKit/Model/NSObject+YYModel.m

+ 37 - 0
YYKit/Model/NSObject+Decodable.swift

@@ -0,0 +1,37 @@
+//
+//  NSObject+Decodable.swift
+//  YYKit
+//
+//  Created by OneeChan on 2025/10/13.
+//
+
+import Foundation
+
+// MARK: 为了从 YYModel 过度到 Decodable,增加解析的兼容代码
+extension Decodable {
+    static func decode(param: [AnyHashable: Any]) -> Self? {
+        guard let jsonData = getJsonData(param) else { return nil }
+        guard let model = try? JSONDecoder().decode(Self.self, from: jsonData) else { return nil }
+        
+        return model
+    }
+    
+    private static func getJsonData(_ param: [AnyHashable: Any]) -> Data? {
+        if !JSONSerialization.isValidJSONObject(param) {
+            return nil
+        }
+        guard let data = try? JSONSerialization.data(withJSONObject: param, options: []) else {
+            return nil
+        }
+        return data
+    }
+}
+
+extension NSObject {
+    @objc static func tryDecode(from param: [AnyHashable: Any]) -> Self? {
+        guard let decodableType = self as? Decodable.Type else {
+            return nil
+        }
+        return decodableType.decode(param: param) as? Self
+    }
+}

+ 5 - 2
YYKit/Model/NSObject+YYModel.m

@@ -1023,8 +1023,11 @@ static void ModelSetValueForProperty(__unsafe_unretained id model,
                         if (meta->_hasCustomClassFromDictionary) {
                             cls = [cls modelCustomClassForDictionary:value] ?: cls;
                         }
-                        one = [cls new];
-                        [one modelSetWithDictionary:value];
+                        one = [cls performSelector:@selector(tryDecodeFrom:) withObject:value];
+                        if (one == nil) {
+                            one = [cls new];
+                            [one modelSetWithDictionary:value];
+                        }
                         ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, (id)one);
                     }
                 }