gpt4 book ai didi

Swift:如何检查泛型类型的对象是否是类型子类型的数组

转载 作者:搜寻专家 更新时间:2023-11-01 05:36:23 24 4
gpt4 key购买 nike

我正在从事一个涉及 Alamofire、ObjectMapper 和 RealmSwift 的 Swift 项目,遇到了一种情况,我必须检查泛型类型的对象是否是 Realm 的 Object 数组。

我的问题是:如何在 Swift 中检查泛型类型的对象是否是某个类型的子类型的数组?

冗长的版本:我为我的问题制作了一个最小工作示例。请看我的gist here .您可以将它复制到 Xcode Playground 并看到第 31 行运行而第 35 行不运行。

我能够通过更改第 70 和 71 行使其工作

来自

if let array = data as? [Object] {
add(array)
}

if let array = data as? NSArray where array.count > 0 && array[0] is Object {
add(array as! [Object])
}

但该解决方案甚至还不够完美,因为它必须涉及 Foundation .我更喜欢“纯粹”的 Swift。

<script src="https://gist.github.com/T-Pham/44fe5b7c3a669db34d856b54e15f278a.js"></script>

已删除:简短版本不能完全代表实际问题。

简短版:

protocol Protocol {
init()
}

class Parent {}
final class Child1: Parent, Protocol {}
final class Child2: Parent, Protocol {}

func foo<T: Protocol>(array: [T]) {
if array is [Parent] { // This won't compile
}
}

foo([Child1(), Child1()])

最佳答案

在 Swift 类型系统中,[Child][Parent] 不相等,因为 Swift 的泛型不支持协变。您可以使用具有泛型类型约束的重载来代替子类型多态性和动态类型转换。

首先,创建三个与 myRequest〜 方法相同的 handleResponse() 方法重载:

func handleResponse(alamofireReponse: AlamofireReponse<AnyObject, NSError>, completionHandler: (MyResponse<AnyObject> -> Void)) {
switch alamofireReponse {
case .Success(let data):
completionHandler(.Success(data))
case .Failure(let error):
completionHandler(.Failure(error))
}
}

func handleResponse<T: Mappable where T: Object>(alamofireReponse: AlamofireReponse<T, NSError>, completionHandler: (MyResponse<T> -> Void)) {
switch alamofireReponse {
case .Success(let data):
add(data)
completionHandler(.Success(data))
case .Failure(let error):
completionHandler(.Failure(error))
}
}

func handleResponse<T: Mappable where T: Object>(alamofireReponse: AlamofireReponse<[T], NSError>, completionHandler: (MyResponse<[T]> -> Void)) {
switch alamofireReponse {
case .Success(let data):
add(data)
completionHandler(.Success(data))
case .Failure(let error):
completionHandler(.Failure(error))
}
}

然后,改变myRequest〜方法的类型约束以满足每个handleResponse方法的约束。

func myRequestObject<T: Mappable where T: Object>(completionHandler: (MyResponse<T> -> Void)) {
responseObject { alamofireReponse in
handleResponse(alamofireReponse, completionHandler: completionHandler)
}
}

func myRequestArray<T: Mappable where T: Object>(completionHandler: (MyResponse<[T]> -> Void)) {
responseArray { alamofireReponse in
handleResponse(alamofireReponse, completionHandler: completionHandler)
}
}

通过这样做,handleResponse () 方法和 add () 方法将在编译时根据参数的类型分派(dispatch)到适当的方法。您不需要动态检查类型。

完整代码如下,以防万一:

import Foundation

// Alamofire
enum AlamofireReponse<T, E> {
case Success(T)
case Failure(E)
}

func responseJSON(alamofireReponse: AlamofireReponse<AnyObject, NSError> -> Void) {
alamofireReponse(.Success([["type": "not_object"], ["type": "not_object"]]))
}

// ObjectMapper
protocol Mappable {
init()
}

// AlamofireObjectMapper
func responseObject<T: Mappable>(alamofireReponse: AlamofireReponse<T, NSError> -> Void) {
alamofireReponse(.Success(T()))
}

func responseArray<T: Mappable>(alamofireReponse: AlamofireReponse<[T], NSError> -> Void) {
alamofireReponse(.Success([T(), T()]))
}

// RealmSwift
class Object {}

func add(object: Object) {
print("adding single object works") // This line would run
}

func add<T: SequenceType where T.Generator.Element: Object>(objects: T) {
print("adding multiple objects works") // This line would not
}

// My code
final class Post: Object, Mappable {}
final class Comment: Object, Mappable {}

enum MyResponse<T> {
case Success(T)
case Failure(NSError)
}

func myRequestJSON(completionHandler: (MyResponse<AnyObject> -> Void)) {
responseJSON { alamofireReponse in
handleResponse(alamofireReponse, completionHandler: completionHandler)
}
}

func myRequestObject<T: Mappable where T: Object>(completionHandler: (MyResponse<T> -> Void)) {
responseObject { alamofireReponse in
handleResponse(alamofireReponse, completionHandler: completionHandler)
}
}

func myRequestArray<T: Mappable where T: Object>(completionHandler: (MyResponse<[T]> -> Void)) {
responseArray { alamofireReponse in
handleResponse(alamofireReponse, completionHandler: completionHandler)
}
}

func handleResponse(alamofireReponse: AlamofireReponse<AnyObject, NSError>, completionHandler: (MyResponse<AnyObject> -> Void)) {
switch alamofireReponse {
case .Success(let data):
completionHandler(.Success(data))
case .Failure(let error):
completionHandler(.Failure(error))
}
}

func handleResponse<T: Mappable where T: Object>(alamofireReponse: AlamofireReponse<T, NSError>, completionHandler: (MyResponse<T> -> Void)) {
switch alamofireReponse {
case .Success(let data):
add(data)
completionHandler(.Success(data))
case .Failure(let error):
completionHandler(.Failure(error))
}
}

func handleResponse<T: Mappable where T: Object>(alamofireReponse: AlamofireReponse<[T], NSError>, completionHandler: (MyResponse<[T]> -> Void)) {
switch alamofireReponse {
case .Success(let data):
add(data)
completionHandler(.Success(data))
case .Failure(let error):
completionHandler(.Failure(error))
}
}

// Usage
myRequestJSON { response in
}

myRequestObject { (response: MyResponse<Post>) in
}

myRequestArray { (response: MyResponse<[Post]>) in
}

关于Swift:如何检查泛型类型的对象是否是类型子类型的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38498330/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com