无法从符合Equatable到AnyObject的对象进行向下转换

时间:2014-09-24 13:26:59

标签: json swift protocols reactive-cocoa

这一直困扰着我。我希望使用Moya + ReactiveCocoajson-swift

如果不重写其中的一些框架似乎并不容易,因为在某一点上我似乎需要返回一个AnyObject,然后创建一些符合Equatable的数据,因此不允许这样做。

这是一个玩具Playground准备示例,用于演示错误消息

struct JSValue: Equatable {
    let value:String
}

func ==(lhs: JSValue, rhs: JSValue) -> Bool {
    return (lhs.value == rhs.value)
}

var jsv = JSValue(value: "abc")
var anyValue = jsv as AnyObject

最后一行错误“无法从JSValue转发到非@objc协议类型'AnyObject'”。

我通常会避免转换为AnyObject,但我一直在尝试使用an implementation of JSValue from json-swift并重复the pattern described inside Moya's implementation of ReactiveCocoa seen with the usage of tryMap here。 tryMap在Moya + RACSignal扩展中所需的回调签名需要返回AnyObject。

对于那些希望看到一个例子而非理解上下文的人,这就是我的意思:

import Foundation

import Moya
import ReactiveCocoa

import JSONLib

/*
let MoyaErrorDomain = "Moya"

public enum MoyaErrorCode: Int {
    case ImageMapping = 0
    case JSONMapping
    case StringMapping
    case StatusCode
    case Data
}
*/

public typealias JSParsingResult = (value: JSValue?, error: Error?)

/// Extension for processing raw NSData generated by network access.
public extension RACSignal {

    /// Maps data received from the signal into a literal JSON type. If the conversion fails, the signal errors.
    public func mapLiteralJSON() -> RACSignal {
        return tryMap({ (object, error) -> AnyObject! in
            var json:AnyObject?
            if let response = object as? MoyaResponse {
                let parsingResult = JSON.parse(response.data)
                json = parsingResult.value! as AnyObject // The same error message as described previously.
            }

            // Note: ignore that I am not handling errors yet...
            /*
            if json == nil && error != nil && error.memory == nil {
                var userInfo: [NSObject : AnyObject]?
                if object != nil {
                    userInfo = ["data": object]
                }

                error.memory = NSError(domain: MoyaErrorDomain, code: MoyaErrorCode.JSONMapping.toRaw(), userInfo: userInfo)
            }
            */

            return json
        })
    }
}

是否有任何快速解决此错误消息的方法,或者我唯一的选择是使用(1)解析不符合Equatable的JSON的不同方法,或者(2)重写Moya以使用the other version of ReactiveCocoa in which tryMap does not return AnyObject,或(3)不使用ReactiveCocoa。

通过避免AnyObject来正确解决这个问题真的很不错,但此时我可能缺乏Swift和ReactiveCocoa技能......

在非技术层面,有什么办法解决这个问题?减少接触未完成的技术是否明智?

3 个答案:

答案 0 :(得分:2)

您遇到了这个问题,因为您正在将为Objective-C编写的库与为Swift编写的库混合使用。

Objective-C id映射到AnyObject,它可以是对任何类的引用。

使用Swift,如果你想要一个可以引用任何的变量,你需要使用Any

此外,对于Swift,我们鼓励您使用结构,其中值类型语义是有意义的,出于性能原因。毫无疑问,这会在Swift库中经常使用结构体。因此,您可以预期Swift库和Objective-C库存在严重的兼容性问题。

答案 1 :(得分:1)

我的临时解决方案,直到Swift版本的ReactiveCocoa发布,这是:

public class WrappedStruct<T> {

    let data:T?

    init(data: T?) {
        self.data = data
    }

}

我能够将该类作为AnyObject传递。这是一个非常hacky的事情,但它至少很容易理解。

答案 2 :(得分:-1)

是的,我知道在Swift中使用struct而不是正确的类是可取的,但我发现以下内容可以解决Playground错误。

class JSValue: Equatable {
    let value:String

    init(value: String) {
        self.value = value
    }
}

func ==(lhs: JSValue, rhs: JSValue) -> Bool {
    return (lhs.value == rhs.value)
}

var jsv = JSValue(value: "abc")
var anyValue = jsv as AnyObject

同样,不理想,但在ReactiveCocoa完全Swift-ified之前,它可能是您唯一的选择。我必须做一些与MoyaResponse类相似的事情。