2014-09-24 57 views
2

這一直纏着我。我想用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

回答

2

,因爲你是混合了對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

-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完全斯威夫特 - 指明分數,那可能是你唯一的選擇。我不得不做類似MoyaResponse類的事情。

1

我的臨時解決方案,直到ReactiveCocoa的斯威夫特版本發佈時是這樣的:

public class WrappedStruct<T> { 

    let data:T? 

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

} 

我能夠通過周圍類視爲一個AnyObject。這是一件很不容易的事情,但它至少容易理解。