简体   繁体   English

如何在Swift中转换为泛型类型

[英]How to cast to generic type in Swift

I am about to learn Swift. 我即将学习Swift。 I want to write a class, that handles Cora Data tasks for me. 我想编写一个类,为我处理Cora Data任务。 In this case, it should be possible to pass an entity name and and array of tuples to a function, which then interprets the tuples as key value pairs for NSPredicates to retrieve ManagedObjects matching them. 在这种情况下,应该有可能将实体名称和元组数组传递给一个函数,然后该函数将元组解释为键值对,以便NSPredicates检索与它们匹配的ManagedObjects。 Because of NSPredicate needing values with specific types, I tried to pass the types of the values, too. 由于NSPredicate需要具有特定类型的值,因此我也尝试传递值的类型。 But I can't get around that "'t' is not a type" compile error (last line of code). 但是我无法解决“'不是'不是类型”的编译错误(代码的最后一行)。 How can I cast the value to an passed type? 如何将值转换为传递的类型? Or would you create the NSPredicate in a totally different way? 还是以完全不同的方式创建NSPredicate?

class func getManagedObjectsWithEntityName<T>(entityName: String, keysAndValues: [(key: String, value: AnyObject, type: T.Type)]) -> [NSManagedObject] {

    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let managedContext = appDelegate.managedObjectContext

    let fetchRequest = NSFetchRequest(entityName: entityName)
    var predicates: [NSPredicate] = []

    for tuple in keysAndValues {
        let t = tuple.type
        predicates.append( NSPredicate(format: tuple.key + " = %@", tuple.value as t)!)
    }

    ...
}

No need to use generics here, you don't seem to need to have to access any of the members / functions of whatever class you would use as a generic. 这里无需使用泛型,您似乎不必访问用作泛型的任何类的成员/函数。

What you do have however is a choice: either you can take values as conforming to CVarArgType, allowing you to plug them straight into your NSPredicate constructor, or you can take values as strings and construct the predicate by building a string expression. 但是,您可以做的是选择:可以采用符合CVarArgType的值,使您可以将其直接插入NSPredicate构造函数中,也可以将值作为字符串,并通过构建字符串表达式来构造谓词。 Here is an example using CVarArgType: 这是使用CVarArgType的示例:

func getManagedObjectsWithEntityName(entityName: String, keysAndValues: 
    [(key: String, value: CVarArgType)]) -> [NSManagedObject] {

    ...

    let fetchRequest = NSFetchRequest(entityName: entityName)
    var predicates: [NSPredicate] = []

    for tuple in keysAndValues {
        predicates.append( NSPredicate(format: "%K = %@", tuple.key, tuple.value))
    }

    ...

}

The reason your generic wasn't working is that you set up a place holder , but then your tuple.type in the function sig was actually T.Type (rather than just T). 泛型不起作用的原因是您设置了一个占位符,但是函数sig中的tuple.type实际上是T.Type(而不只是T)。 If you changed the tuple specification to (key: String, value: AnyObject, type: T) then you would be able to cast let t = tuple.type as! T 如果将元组规范更改为(key: String, value: AnyObject, type: T)则可以将let t = tuple.type as! T let t = tuple.type as! T . let t = tuple.type as! T But then you would run into problems as NSPredicate doesn't take type T - whence the solution not really being to use generics, but instead use something like the above. 但是然后您会遇到问题,因为NSPredicate没有采用T类型-那里的解决方案不是真正使用泛型,而是使用类似上面的内容。 It's also worth bearing in mind it's a good idea to avoid using variable names such as .type and .value, as in certain cases these will cause confusion with things, especially with NSManagedObjects (which have .value). 还应记住,避免使用诸如.type和.value之类的变量名是个好主意,因为在某些情况下,它们会引起事物的混淆,尤其是与NSManagedObjects(具有.value的事物)。 At least it's worth knowing that this can be a cause of issues... 至少值得知道这可能是问题的原因...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM