2015-11-11 52 views
7

我正在嘗試在swift中爲我們的應用製作一個簡單的依賴注入系統,現在爲期2天。我對任何解決方案都很靈活,但是我想要一些東西,所以我可以說「給我一個符合這個協議的東西的實例」,只要符合上述協議,返回的實際類型可以是任何東西。我已經嘗試了很多事情,包括仿製藥,但設法弄清楚,不能真正工作,所以現在我只剩下光禿禿的基礎,這樣的事情(?):檢查類是否符合協議

protocol AProtocol { 

} 

class AClass: AProtocol { 

} 

class MyDiThing { 
    public static func objectConformingTo(aProtocol: Any) -> Any? { 
     // And here I want to do something like 
     if AClass is aProtocol { 
      return AClass() 
     } 
     return nil 
    } 
} 

// The calling code .. 
let aObject = MyDIThing.objectConformingTo(AProtocol) 

它不漂亮,我知道,但現在我沒有那麼挑剔性能/錯誤的代碼,只要它解決了解耦問題(最好可以包含在MyDIThing類中)。如果這是不可能的,我很樂意接受其他解決方案。我用Objective-C的類似解決方案取得了很好的成功,只有一個字典的鍵是NSStringFromProtocol,值是類,用入站協議爲字典下標並實例化類。超級簡單。迅速感覺不可能!

回答

4

如果你導入obj-c,那麼你可以做一些像你以前一樣的東西。

否則,這很難,因爲協議不以相同的方式存在。考慮一下工廠的註冊系統。您的每個類都將通過提供一個函數或閉包來註冊自己,這個函數或閉包可以被調用來返回該類的新實例,並且註冊是針對字符串或其他類型的標識符的。這是一個協議類型的好處,但在obj-c中,你真的用字符串轉換做同樣的事情。你可以註冊任何Equatable,以保持非常通用的東西。

+8

'if let foo = bar as? MyProtocol {/ * bar符合協議...... foo是MyProtocol類型,並且可以調用方法* /}' – nhgrif

+0

我最終使用enum作爲鍵和閉包作爲值來執行基於註冊的swift方法。效果很好。 –

7

通過nhgrif給出的註釋是斯威夫特2 正確的答案,您應該使用一個可選的綁定:

if let aObjectWithAProtocol = aObject as? AProtocol { 
    // object conforms to protocol 
    someObject.someFunction(aObjectWithAProtocol) 
} else { 
    // object does not conform to protocol 
} 

if let something = obj as? type語句被稱作可選結合並檢查對象可以是輸入到給定的類型/類別/協議/ ....

如果是這樣,您可以使用可選的(as?)或force unwrapas!)該對象。

0

此功能將完全滿足您的要求:

bool _swift_typeIsTargetType(id sourceType, id targetType)

它可以檢查一個迅速的類型是目標類型(爲相同類型或子類,或者符合目標協議),就像is快速操作員。但它是一個類型,而不是一個實例:

let sourceType: Any.Type = type(of: self) 
let targetType: Any.Type = AnyProtocol.self 
let result = _swift_typeIsTargetType(sourceType, targetType) 

它使用專用的API在libswiftCore.dylib,見迅速源代碼Casting.cpp

bool _conformsToProtocols(const OpaqueValue *value, const Metadata *type, const ExistentialTypeMetadata *existentialType, const WitnessTable **conformances) 

可選的結合是不一樣的。它還可以檢查一致性,但你不能動態地給類型檢查:

let targetType: Any.Type = AnyProtocol.self 
//error: use of undeclared type: 'targetType' 
if let _ = aObject as? targetType { 
    // object conforms to protocol 
} else { 
    // object does not conform to protocol 
} 

這個功能在使用ZIKRouter。它是一個模塊路由器,也是一個依賴注入框架。它使用協議來發現模塊並注入依賴關係。如果你想做'找到符合某種協議的模塊',你可以試試它。