无法从符合Equatable对象向下转换AnyObject

问题描述:

这一直缠着我。我想用Moya + ReactiveCocoajson-swift无法从符合Equatable对象向下转换AnyObject

这似乎并不容易,而不需要重写一些这些框架截至看来我需要返回一个AnyObject和尚未建立一些数据符合Equatable,因此不允许这样一个点。

这里是一个玩具游乐场就绪例子来说明的错误消息与

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。在Moya + RACSignal扩展中,tryMap所需的回调的签名要求返回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)解析JSON的不同方法,该方法不符合Equatable,或(2)重写莫亚使用the other version of ReactiveCocoa in which tryMap does not return AnyObject,或(3)不使用ReactiveCocoa。

这将是非常好的避免AnyObject妥善解决这个问题,但在这一点上,我可能既缺少斯威夫特和ReactiveCocoa能力这样做......

在非技术层面,有什么办法在这附近?减少我对未完成技术的接触会是明智的吗?

+2

如果你把它变成一个类而不是一个结构会怎样? – Arno 2014-09-24 13:45:43

+0

问题是我不控制这段代码。符合Equatable的结构来自json-swift在Swift中更好地处理JSON的抽象。 – olive 2014-09-24 13:47:02

+3

当然,您不能将结构向下翻到“AnyObject”,但是可以将结构强制转换为“Any”类型。 – tikhop 2014-09-24 13:57:27

,因为你是混合了对Objective-C的与那些被用于斯威夫特写书面库您已经打到了这个问题。

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

使用Swift,如果你想要一个变量,可以参考任何东西你需要使用Any

此外,出于性能方面的原因,使用Swift,鼓励您使用结构,其中值类型的语义是有意义的。这无疑会导致在Swift库中频繁使用结构。因此,您可能会预期与Swift库和Objective-C库存在重大的兼容性问题。

+0

复制属性。“此外,使用Swift,我们鼓励你使用结构性能原因。“你有没有从苹果引用?结构有好处,但我不了解性能如何成为选择它们的原因。 – 2014-09-24 14:38:25

+0

有没有办法解决这个兼容性问题,或者这是完全不可能的? – olive 2014-09-24 14:51:50

+1

@RobNapier对不起,这句话很模糊,有点清晰。更准确地说,出于性能原因,应该使用结构(值类型语义有意义)。你可以在这里看到一个影响的例子:http://blog.human-friendly.com/optimising-swift-with-functional-style-50x-speed-boost-from-changing-1-keyword我没有一个引用,但有苹果工程师的反馈。提高性能的潜力应该非常明显,常量结构完全不可变,而常量类不是。 – ColinE 2014-09-24 14:57:07

是的,我知道在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完全斯威夫特 - 指明分数,那可能是你唯一的选择。我不得不做类似MoyaResponse类的事情。

我的临时解决方案,直到ReactiveCocoa的斯威夫特版本发布时是这样的:

public class WrappedStruct<T> { 

    let data:T? 

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

} 

我能够通过周围类视为一个AnyObject。这是一件很不容易的事情,但它至少容易理解。