Swift - 无条件动态投射类? [英] Swift - Dynamic cast class unconditional?

查看:120
本文介绍了Swift - 无条件动态投射类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



基本上是这样的问题:

  // T定义为T:NSObject 
let oebj1 = NetworkResponse< User>()
let oebj2 = oebj1 as NetworkResponse< NSObject>

这就是为什么我需要做这个铸造

  class BaseViewController:UIViewController {

//不允许创建一个通用的viewController,因此必须将泛型转换为NSObject
func fetchData(完成:(NetworkResponse< NSObject>) - >()){
fatalError(您必须实现fetchData方法)
}


$ b $ class UsersViewController:BaseViewController {
覆盖func fetchData(完成:(NetworkResponse< NSObject>) - &()){
userNetworkManager.fetchUsers {networkUSerResponse in
completion(networkUSerResponse as NetworkResponse< NSObject>)
}
}
}

class UserNetworkManager {
func fetchUsers(完成:(NetworkResponse< User> ;) - >()){
//做东西
}
}


解决方案

总的来说,似乎没有办法做到这一点。基本问题是 NetworkResponse< NSObject> NetworkResponse<用户> 实际上是完全不相关的类型,功能和类似的命名。

在这种特殊情况下,它确实没有必要,因为您将已知的 User 用户以后,你必须做一个有条件的转换。只需从 NetworkResponse 中删除​​泛型,它将按预期工作。主要的缺点是在 UserVC.fetchData 中,你将无法访问返回的 User )cast。

另一种解决方案是从负载类型中分离出 NetworkResponse 中的任何附加信息用户 / NSObject )使用某种类型的包装(假设存在重要的边带数据)。通过这种方式,您可以将 NetworkResponse 传递给super,而不会造成损坏,并根据需要向下转换有效内容对象。

Something像这样:

  class User:NSObject {
}

class Transaction {
让请求:NSURLRequest?
让回应:NSURLResponse?
让数据: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(完成:(Response<用户>) - >()) {
completion(Response(transaction:Transaction(),payload:User()))
}
}

let userNetworkManager = UserNetworkManager();
$ b class BaseVC {
func fetchData(completion:(Response< NSObject>) - >()){
fatalError(Gotta implement fetchData)
}

$ b class UserVC:BaseVC {
覆盖func fetchData(完成:(Response< NSObject>) - >()){
userNetworkManager.fetchUsers {response - > ()in
completion(Response(transaction:response.transaction,payload:response.payload))
}
}
}

虽然在这一点上,您最好将交易信息和有效负载信息分隔成不同的回调参数。


It doesn't seem like I can cast a generic type to another? Swift is throwing DynamicCastClassException.

Basically here is the problem:

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

Here is why I need to do this casting

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
   }
}

解决方案

In general, there doesn't seem to be a way to do this. The basic problem is that NetworkResponse<NSObject> and NetworkResponse<User> are essentially completely unrelated types that happen to have identical functionality and similar naming.

In this specific case, it really isn't necessary since you're throwing away the known Userness of the result anyway, meaning that if you really want to treat it as a User later you'll have to do a conditional cast back. Just remove the generic from NetworkResponse and it will all work as expected. The major drawback is that within UserVC.fetchData you won't have access to the returned User result without a (conditional) cast.

The alternative solution would be to separate out whatever additional information is in NetworkResponse from the payload type (User/NSObject) using a wrapper of some sort (assuming there's significant sideband data there). That way you could pass the NetworkResponse to super without mutilation and down-cast the payload object as needed.

Something like this:

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))
        }
    }
}

Although at that point, you're probably better off just separating the transaction information and payload information into separate arguments to the callback.

这篇关于Swift - 无条件动态投射类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆