Swift - 动态演员类无条件?

时间:2015-01-23 17:56:31

标签: ios generics swift

似乎我不能将泛型类型转换为另一种类型? Swift抛出DynamicCastClassException。

基本上就是问题所在:

// T is defined as T: NSObject
let oebj1 = NetworkResponse<User>()
let oebj2 = oebj1 as NetworkResponse<NSObject>

这就是为什么我需要做这个演员

class BaseViewController: UIViewController {

   // Not allowed to make a generic viewController and therefore have to cast the generic down to NSObject
   func fetchData(completion: (NetworkResponse<NSObject>)->()) {
      fatalError("You have to implement fetchData method")
   }

}

class UsersViewController: BaseViewController  {
    override func fetchData(completion: (NetworkResponse<NSObject>)->()) {
        userNetworkManager.fetchUsers { networkUSerResponse in
            completion(networkUSerResponse as NetworkResponse<NSObject>)
        }
    }
}

class UserNetworkManager {
   func fetchUsers(completion: (NetworkResponse<User>)->()) {
      // Do stuff
   }
}

1 个答案:

答案 0 :(得分:2)

一般来说,似乎没有办法做到这一点。基本问题是NetworkResponse<NSObject>NetworkResponse<User>基本上是完全不相关的类型,恰好具有相同的功能和相似的命名。

在这种特定的情况下,实际上没有必要,因为你无论如何都要丢弃结果的已知User,这意味着如果你真的想在以后将其视为User你必须做一个条件反弹。只需从NetworkResponse删除通用,它就会按预期工作。主要缺点是在UserVC.fetchData内,如果没有(条件)强制转换,您将无法访问返回的User结果。

替代解决方案是使用某种包装器(假设有重要的边带数据)从有效负载类型(NetworkResponse / User)中分离NSObject中的任何其他信息那里)。这样你可以将NetworkResponse传递给super而不进行切割,并根据需要向下转换有效负载对象。

这样的事情:

class User : NSObject {
}

class Transaction {
    let request:NSURLRequest?
    let response:NSURLResponse?
    let data:NSData?
}

class Response<T:NSObject> {
    let transaction:Transaction
    let payload:T

    init(transaction:Transaction, payload:T) {
        self.transaction = transaction
        self.payload = payload
    }
}


class UserNetworkManager {
    func fetchUsers(completion: (Response<User>) -> ()) {
        completion(Response(transaction:Transaction(), payload:User()))
    }
}

let userNetworkManager = UserNetworkManager();

class BaseVC {
    func fetchData(completion: (Response<NSObject>) -> ()) {
        fatalError("Gotta implement fetchData")
    }
}

class UserVC : BaseVC {
    override func fetchData(completion: (Response<NSObject>) -> ()) {
        userNetworkManager.fetchUsers { response -> () in
            completion(Response(transaction: response.transaction, payload: response.payload))
        }
    }
}

虽然此时,您可能最好将事务信息和有效负载信息分离为回调的单独参数。