竞争条件和递归:在下一行执行之前不返回字典

问题描述 投票:0回答:1

期望的结果

  1. 使用fixedValues作为dictionaryRepresentation参数初始化MyClass。
  2. 在执行 init 行之前设置固定值

问题

    在运行
  • self.init(
    ... 行之前未设置 
    fixedValues。

尝试的解决方案

  1. 返回而不是完成(发布状态)
  2. 完成、调度组、通知
  3. 信号量等待设置
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
    }
}
ios swift recursion tree grand-central-dispatch
1个回答
0
投票

我真的不确定你想在这里做什么。

我尝试在操场上编写代码(我不得不猜测很多代码),但它对我有用。

这是我的代码:

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 类中,它似乎没有在任何地方使用。因此,我不会在这里使用完成处理程序,因为当它是简单的线性代码时,它会使代码难以阅读。

© www.soinside.com 2019 - 2024. All rights reserved.