在功能上接收正确的类型

时间:2018-01-30 16:54:57

标签: swift macos cocoa

我尝试构建一些NestedView,它在视图内部加载视图...取决于对象树。所以我在Playground做了一个简短的测试:

class First {}
class Second:First {}

class Dodd {
    func takeIt<Foo, Bar>(content:[Foo], type: Bar.Type) {
        print (Foo.self, Bar.self)
     print (content as? [Bar] ?? [])
    }
}

let arrayOfFirst:[First] = [First()]
let arrayOfSecond:[Second] = [Second(), Second(), Second()]

let dodd = Dodd()

let firstType = First.self
let secondType = Second.self

dodd.takeIt(content: arrayOfSecond, type: firstType)
dodd.takeIt(content: arrayOfFirst, type: secondType)

它产生了良好且可预测的输出:

Second First
[__lldb_expr_77.Second, __lldb_expr_77.Second, __lldb_expr_77.Second]
First Second
[]

大。 但是,如果我尝试在更复杂的环境中使用完全相同的机制,结果就不那么令人满意了。 这是一些ViewController的功能,无论如何:

func addSubviews<HeadType>(for content:[HeadType]) {

        Swift.print("ADD SUBVIEW FOR \(HeadType.self)")

        func takeNext <ParentType, ChildType>(
            parentArray: [ParentType],
            pathToChild: AnyKeyPath,
            type: ChildType.Type?) -> [ChildType]

        {
            Swift.print ("\nInside takeNext Child Type <\(ChildType.self)>\n")
            let result:[ChildType] = parentArray.flatMap { ( parentElement ) -> ChildType? in
                parentElement [keyPath:pathToChild] as? ChildType}
            return result
        }

        let interfaceHead = InterfaceElements(type: HeadType.self)
        Swift.print ("\tParentArrayContent: \(HeadType.self) ")
        for (label, path) in interfaceHead.paths {

            if let firstObject = content.first, let objectAtKeyPath = firstObject[ keyPath:path ] {
                Swift.print ("\t\tpath: \(path)")
                Swift.print ("\t\ttype: \(InterfaceElements(element: objectAtKeyPath).type.self)")
                Swift.print("\t\tLabel", label)
                let childType = InterfaceElements(element: objectAtKeyPath).type
                let elements = takeNext(
                    parentArray: content,
                    pathToChild: path,
                    type: childType)

                let controller = NestedStackViewController(for: elements)

            }
        }
    }

输出:

ADD SUBVIEW FOR Joint
    ParentArrayContent: Joint 
        path: Swift.ReferenceWritableKeyPath<HyperGlyph.Joint, Swift.ImplicitlyUnwrappedOptional<HyperGlyph.Position>>
        type: Optional(HyperGlyph.Position)
        Label position

Inside takeNext Child Type <NSManagedObject>

ADD SUBVIEW FOR NSManagedObject
    ParentArrayContent: NSManagedObject 
inited NestedStack for  NSManagedObject
inited NestedStack for  Joint

第一个循环很好,Joint是Joint,找到了Position类型,发送到takeNext,但是在takeNext函数里面的位置变成了NSManagedObject类型。哪里可以欺骗?

1 个答案:

答案 0 :(得分:0)

只有一种方法是明确传递一种类型。

let elements = takeNext(
                parentArray: content,
                pathToChild: path,
                type: SomeType.self) // << Here.

它使程序更复杂,更switch es,但它现在以强大的方式工作。