Skip to content

Commit

Permalink
发布V4.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Mccc committed Oct 8, 2024
1 parent 3c8bac8 commit b17d751
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 76 deletions.
4 changes: 2 additions & 2 deletions Example/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ PODS:
- FBSnapshotTestCase/SwiftSupport (2.1.4):
- FBSnapshotTestCase/Core
- HandyJSON (5.0.0-beta.1)
- SmartCodable (4.2.1)
- SmartCodable (4.2.2)
- SnapKit (5.6.0)

DEPENDENCIES:
Expand Down Expand Up @@ -39,7 +39,7 @@ SPEC CHECKSUMS:
CleanJSON: 910a36465ce4829e264a902ccf6d1455fdd9f980
FBSnapshotTestCase: 094f9f314decbabe373b87cc339bea235a63e07a
HandyJSON: 582477127ab3ab65bd2e471815f1a7b846856978
SmartCodable: ad311e84a90b09a85ba8f963ec16d30bc11fed19
SmartCodable: 4f52d801dbd15856fabb69110d24f31f49145734
SnapKit: e01d52ebb8ddbc333eefe2132acf85c8227d9c25

PODFILE CHECKSUM: 7f3af03f81934df0c035518074a7abbec8fa9d3f
Expand Down
4 changes: 2 additions & 2 deletions Example/Pods/Local Podspecs/SmartCodable.podspec.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Example/Pods/Manifest.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Example/SmartCodable.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -823,10 +823,12 @@
TargetAttributes = {
607FACCF1AFB9204008FA782 = {
CreatedOnToolsVersion = 6.3.1;
DevelopmentTeam = RA2G5HURUT;
LastSwiftMigration = 0900;
};
607FACE41AFB9204008FA782 = {
CreatedOnToolsVersion = 6.3.1;
DevelopmentTeam = RA2G5HURUT;
LastSwiftMigration = 0900;
TestTargetID = 607FACCF1AFB9204008FA782;
};
Expand Down Expand Up @@ -1239,6 +1241,7 @@
baseConfigurationReference = BC656B63C9031B22DEB5C8EB /* Pods-SmartCodable_Example.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = RA2G5HURUT;
INFOPLIST_FILE = SmartCodable/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
Expand All @@ -1255,6 +1258,7 @@
baseConfigurationReference = AD8215B5E8E50F277C1C4356 /* Pods-SmartCodable_Example.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = RA2G5HURUT;
INFOPLIST_FILE = SmartCodable/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
Expand All @@ -1270,6 +1274,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = DB7246035010143E03C7616B /* Pods-SmartCodable_Tests.debug.xcconfig */;
buildSettings = {
DEVELOPMENT_TEAM = RA2G5HURUT;
FRAMEWORK_SEARCH_PATHS = (
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
"$(inherited)",
Expand All @@ -1293,6 +1298,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = AFEADC35BC2373F1DC69B73B /* Pods-SmartCodable_Tests.release.xcconfig */;
buildSettings = {
DEVELOPMENT_TEAM = RA2G5HURUT;
FRAMEWORK_SEARCH_PATHS = (
"$(PLATFORM_DIR)/Developer/Library/Frameworks",
"$(inherited)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@ import SmartCodable
class Introduce_12ViewController: BaseViewController {
var cancellables = Set<AnyCancellable>()

var model: PublishedModel?

override func viewDidLoad() {
super.viewDidLoad()

let dict: [String: Any] = [
"newName": 1,
"name": 1,
"age": "333333"
]

if let model = PublishedModel.deserialize(from: dict) {

self.model = model
print("反序列化后的 name 值: \(model.name)")

// 正确访问 name 属性的 Publisher
Expand All @@ -31,10 +35,14 @@ class Introduce_12ViewController: BaseViewController {
}
.store(in: &cancellables)

// 修改 model 的 name 属性
model.name = "Updated iOS Developer"

}
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// 修改 model 的 name 属性
model?.name = "Updated iOS Developer"
}
}

// 定义 PublishedModel,并实现反序列化
Expand All @@ -43,28 +51,22 @@ class PublishedModel: ObservableObject, SmartCodable {

@SmartPublished
var name: String = "iOS Developer"

static func mappingForKey() -> [SmartKeyTransformer]? {
[CodingKeys.name <--- "newName"]
}

// static func mappingForValue() -> [SmartValueTransformer]? {
// [
// CodingKeys.name <--- PublishedValueTransformer(),
// ]
//
// static func mappingForKey() -> [SmartKeyTransformer]? {
// [CodingKeys.name <--- "newName"]
// }
}

struct PublishedValueTransformer: ValueTransformable {
func transformFromJSON(_ value: Any) -> String? {
return "good"
}

func transformToJSON(_ value: String) -> String? {
return "gooooooood"
}

typealias Object = String

typealias JSON = String
}
//struct PublishedValueTransformer: ValueTransformable {
// func transformFromJSON(_ value: Any) -> String? {
// return "good"
// }
//
// func transformToJSON(_ value: String) -> String? {
// return "gooooooood"
// }
//
// typealias Object = String
//
// typealias JSON = String
//}
17 changes: 6 additions & 11 deletions Example/SmartCodable/Test2ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,17 @@ class Test2ViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()

let model = Model()

let json = model.toDictionary()

print(json)
let dict = [
"name": 1.22222
]
let model = Model.deserialize(from: dict)
print(model)

}

struct Model: SmartCodable {
var name: String = "Mccc"

@IgnoredKey(supportEncode: false)
var ignore1: String = "忽略的key1"
var name: String = ""

@IgnoredKey(supportEncode: true)
var ignore2: String = "忽略的key2"

}
}
3 changes: 0 additions & 3 deletions Example/SmartCodable/TestViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,10 @@ import BTPrint
*/



class TestViewController: BaseViewController {

override func viewDidLoad() {
super.viewDidLoad()



}
}
2 changes: 1 addition & 1 deletion SmartCodable.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

Pod::Spec.new do |s|
s.name = 'SmartCodable'
s.version = '4.2.1'
s.version = '4.2.2'
s.summary = '数据解析库'

s.homepage = 'https://github.com/intsig171'
Expand Down
88 changes: 59 additions & 29 deletions SmartCodable/Classes/SmartType/SmartPublished.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,50 +26,80 @@ public protocol SmartPublishedProtocol {
static func createInstance(with value: Any) -> Self?
}

/// PublishedContainer
/// @Published使属性成为一个发布者,自动发布变更。
/// ObservableObject可以被SwiftUI或其他观察者订阅以监听其变化。
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
public class PublishedContainer<Value>: ObservableObject {
@Published public var wrappedValue: Value

public init(wrappedValue: Value) {
self.wrappedValue = wrappedValue
}
}


/// 属性包装器SmartPublished,允许在声明属性时附加额外的行为。
/// container使用PublishedContainer管理值和发布功能。
/// wrappedValue提供对实际值的访问。
/// projectedValue提供一个发布者,可供订阅。
@propertyWrapper
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
public struct SmartPublished<Value: Codable>: Codable {
private var container: PublishedContainer<Value>

public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let value = try container.decode(Value.self)
self.wrappedValue = value
publisher = Publisher(wrappedValue)
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self.wrappedValue)
}
public var wrappedValue: Value {
get { container.wrappedValue }
set { container.wrappedValue = newValue }
// willSet 观察器在 wrappedValue 被修改前调用,会将新的值通过 publisher 发送出去,从而通知所有的订阅者。这实现了数据更新的响应式特性。
willSet {
publisher.subject.send(newValue)
}
}

public var projectedValue: Published<Value>.Publisher {
container.$wrappedValue
public var projectedValue: Publisher {
publisher
}

public init(wrappedValue: Value) {
self.container = PublishedContainer(wrappedValue: wrappedValue)
private var publisher: Publisher

public struct Publisher: Combine.Publisher {
public typealias Output = Value
public typealias Failure = Never

// CurrentValueSubject 是 Combine 中的一种 Subject,它会保存当前值并向新订阅者发送当前值。相比于 PassthroughSubject,它在初始化时就要求有一个初始值,因此更适合这种包装属性的场景。
var subject: CurrentValueSubject<Value, Never>

// 这个方法实现了 Publisher 协议,将 subscriber 传递给 subject,从而将订阅者连接到这个发布者上。
public func receive<S>(subscriber: S) where S: Subscriber, Self.Failure == S.Failure, Self.Output == S.Input {
subject.subscribe(subscriber)
}

// Publisher 的构造函数接受一个初始值,并将其传递给 CurrentValueSubject 的初始化方法。
init(_ output: Output) {
subject = .init(output)
}
}

public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let value = try container.decode(Value.self)
self.container = PublishedContainer(wrappedValue: value)
public init(wrappedValue: Value) {
self.wrappedValue = wrappedValue
publisher = Publisher(wrappedValue)
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self.wrappedValue)

/// 这个下标实现了对属性包装器的自定义访问逻辑,用于在包装器内自定义 wrappedValue 的访问和修改行为。
/// 参数解析:
/// observed:观察者,即外部的 ObservableObject 实例。
/// wrappedKeyPath:指向被包装值的引用键路径。
/// storageKeyPath:指向属性包装器自身的引用键路径。
public static subscript<OuterSelf: ObservableObject>(
_enclosingInstance observed: OuterSelf,
wrapped wrappedKeyPath: ReferenceWritableKeyPath<OuterSelf, Value>,
storage storageKeyPath: ReferenceWritableKeyPath<OuterSelf, Self>
) -> Value {
get {
observed[keyPath: storageKeyPath].wrappedValue
}
set {
// 在设置新值之前,如果 observed 的 objectWillChange 属性是 ObservableObjectPublisher 类型,则它会发送通知,确保在属性值更新之前,订阅者能收到通知。
if let subject = observed.objectWillChange as? ObservableObjectPublisher {
subject.send() // 修改 wrappedValue 之前
observed[keyPath: storageKeyPath].wrappedValue = newValue
}
}
}
}

Expand Down

0 comments on commit b17d751

Please sign in to comment.