期望的结果
问题
self.init(
... 行之前未设置fixedValues。
尝试的解决方案
class WaitForValue {
private var semaphore = DispatchSemaphore(value: 0)
var valueToWaitFor: String? {
didSet {
if valueToWaitFor != nil {
semaphore.signal()
}
}
}
func waitForValue() {
_ = semaphore.wait(timeout: .distantFuture)
}
}
let waitForValueInstance = WaitForValue()
// This will block until valueToWaitFor is set to a non-nil value
DispatchQueue.global().async {
waitForValueInstance.waitForValue()
print("Value received: \(waitForValueInstance.valueToWaitFor ?? "nil")")
}
// Simulate setting the value after some delay
DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
waitForValueInstance.valueToWaitFor = "Hello, World!"
}
我的代码:
class MyClass {
convenience init?(_ object: Object) {
guard let values = object.getValues(forKeys: MyAttributes.allAttributes) else { return nil }
var fixedValues = values
MyClass.correctedValues(object: object, values: values) { correctedValues in
fixedValues = correctedValues
}
self.init(dictionary: fixedValues, type: object.type)
}
private static func correctedValues(object: Object, values: [String: Any], completion: @escaping([String: Any]) -> Void) {
var valuesDictionary = values
let fixes = objectFixes(object: object)
let valueObjects = values["children"] as? [Object] ?? []
var wrappedObjects = [WrappedObject]()
valueObjects.forEach {
let wrapped = WrappedObject($0)
wrappedObjects.append(wrapped)
}
fixedChildrenValues(originalValues: wrappedObjects, fixes: fixes) { correctedChildren in
valuesDictionary["children"] = correctedChildren
completion(valuesDictionary)
}
}
private static func fixedChildrenValues(originalValues: [WrappedObject], fixes: [String: [Attribute: String]], completion: @escaping ([[String: Any]]) -> Void) {
var fixedChildrenArray = [[String: Any]]()
for childValue in originalValues {
var childAttributes = childValue.getValues(forKeys: [
"children",
"identifier",
"props",
"name"
]) ?? [:]
// Apply fixes
if let matchingIdentifier = childAttributes["identifier"] as? String,
let fix = fixes[matchingIdentifier] {
fix.forEach { (key, value) in
childAttributes[key] = value
}
}
// Attempt to extract child elements and continue traversal
if let childrenObjects = childAttributes["children"] as? [Object] {
var wrappedObjects = [WrappedObject]()
for childObject in childrenObjects {
wrappedObjects.append(WrappedObject(childObject))
}
if !wrappedObjects.isEmpty {
fixedChildrenValues(originalValues: wrappedObjects, fixes: fixes) { correctedChildren in
childAttributes["children"] = correctedChildren
fixedChildrenArray.append(childAttributes)
}
} else {
fixedChildrenArray.append(childAttributes)
}
} else {
fixedChildrenArray.append(childAttributes)
}
}
completion(fixedChildrenArray)
}
private static func objectFixes(object: Object) -> [String: [Attribute: String]] {
var objectFixes = [String: [Attribute: String]]()
let objects = object.objects
for i in 0..<objects.count {
let obj = objects[i]
if !obj.isEnabled {
objectFixes[obj.identifier] = ["props": "false"]
}
}
return objectFixes
}
}
我真的不确定你想在这里做什么。
我尝试在操场上编写代码(我不得不猜测很多代码),但它对我有用。
这是我的代码:
class MyClass {
init(dictionary: [String: Any], type: String) {
print("main init")
}
convenience init?(_ object: Object) {
guard let values = object.getValues(forKeys: MyAttributes.allAttributes) else { return nil }
var fixedValues = values
print(fixedValues)
MyClass.correctedValues(object: object, values: values) { correctedValues in
fixedValues = correctedValues
}
self.init(dictionary: fixedValues, type: object.type)
}
private static func correctedValues(object: Object, values: [String: Any], completion: @escaping([String: Any]) -> Void) {
var valuesDictionary = values
let fixes = objectFixes(object: object)
let valueObjects = values["children"] as? [Object] ?? []
var wrappedObjects = [WrappedObject]()
valueObjects.forEach {
let wrapped = WrappedObject($0)
wrappedObjects.append(wrapped)
}
fixedChildrenValues(originalValues: wrappedObjects, fixes: fixes) { correctedChildren in
valuesDictionary["children"] = correctedChildren
completion(valuesDictionary)
}
}
private static func fixedChildrenValues(originalValues: [WrappedObject], fixes: [String: [Attribute: String]], completion: @escaping ([[String: Any]]) -> Void) {
var fixedChildrenArray = [[String: Any]]()
for childValue in originalValues {
var childAttributes = childValue.getValues(forKeys: [
"children",
"identifier",
"props",
"name"
]) ?? [:]
// Apply fixes
if let matchingIdentifier = childAttributes["identifier"] as? String,
let fix = fixes[matchingIdentifier] {
fix.forEach { (key, value) in
childAttributes[key] = value
}
}
// Attempt to extract child elements and continue traversal
if let childrenObjects = childAttributes["children"] as? [Object] {
var wrappedObjects = [WrappedObject]()
for childObject in childrenObjects {
wrappedObjects.append(WrappedObject(childObject))
}
if !wrappedObjects.isEmpty {
fixedChildrenValues(originalValues: wrappedObjects, fixes: fixes) { correctedChildren in
childAttributes["children"] = correctedChildren
fixedChildrenArray.append(childAttributes)
}
} else {
fixedChildrenArray.append(childAttributes)
}
} else {
fixedChildrenArray.append(childAttributes)
}
}
completion(fixedChildrenArray)
}
private static func objectFixes(object: Object) -> [String: [Attribute: String]] {
var objectFixes = [String: [Attribute: String]]()
let objects = object.objects
for i in 0..<objects.count {
let obj = objects[i]
if !obj.isEnabled {
objectFixes[obj.identifier] = ["props": "false"]
}
}
return objectFixes
}
}
typealias Attribute = String
//enum Attribute:String, Hashable {
// case props
//}
class Object {
let type: String = ""
let objects:[SomeObject] = []
func getValues(forKeys:[String]) -> [String: Any]? {
return ["a": 1, "b": 2]
}
}
struct SomeObject {
var isEnabled: Bool
var identifier: Attribute
}
class WrappedObject {
func getValues(forKeys:[String]) -> [String : Any]?{
return [:]
}
init(_ obj: Object){
}
}
struct MyAttributes{
static var allAttributes: [String] = []
}
MyClass(Object())
这是我得到的照片:
["a": 1, "b": 2]
main init
这表明fixedValue是在调用self.init之前设置的。
而且我对这里的设计模式不太有信心。 在我看来,你应该使用工厂模式而不是方便的 init。
但也许我错过了一些东西。
最后,我没有看到任何异步代码(除了在 WaitForValue 类中,它似乎没有在任何地方使用。因此,我不会在这里使用完成处理程序,因为当它是简单的线性代码时,它会使代码难以阅读。