TLDR:Foo!
であるかのように扱いFoo
ます。
多くの Cocoa 呼び出しには暗黙的にアンラップされたオプションが含まれており、その必要性がこの機能が存在する理由である可能性が非常に高いです。こう考えるとおすすめです。
まず、 を含まない、より単純なケースについて考えてみましょうAnyObject
。UIDevice
良い例だと思います。
class func currentDevice() -> UIDevice!
何が起きてる?まあ、常にありcurrentDevice
ます。これが返された場合nil
は、システムに何らかの深刻なエラーがあることを示しています。したがって、このインターフェースを Swift で構築していた場合、これは返されて処理UIDevice
が完了する可能性があります。しかし、 を返す Objective-C にブリッジする必要がありますUIDevice*
。これは決してnil
であってはなりませんが、構文的には になる可能性がありますnil
。現在、ObjC では、通常、その事実を無視し、ここではチェックしませんnil
(特に、nil
メッセージングは通常安全であるため)。
では、この状況を Swift でどのように表現するのでしょうか? 技術的には であり、最終的には次のようOptional<UIDevice>
になります。
class func currentDevice() -> UIDevice?
そして、それを使用するたびに(理想的にはif let
ブロックで)明示的にアンラップする必要があります。それはすぐにあなたを狂気に駆り立てます。currentDevice()
常に値を返します。これOptional
は、ObjC へのブリッジングのアーティファクトです。
そこで、彼らはそれを回避するためのハックを発明しました (これは本当にハックだと思います。ObjC が混ざっていなければ、この機能を構築することは想像できません)。そのハックは、はい、それはですが、そうでOptional
はないふりをすることができ、常に値になることを約束します。
そして、それは!
です。この種のものについては、基本的に を無視し、!
それがあなたに戻ってきたふりをしてUIDevice
ロールアローンします。彼らがあなたに嘘をついて戻ってきたらnil
、まあ、それはクラッシュするでしょう. 彼らはあなたに嘘をつくべきではありませんでした。
これはルールを示唆しています:!
本当に必要でない限り使用しないでください (そして、ほとんどの場合、ObjC にブリッジする場合にのみ使用する必要があります)。
あなたの特定の例では、これは両方向に機能します:
func valueForAttribute(key: String!) -> AnyObject!
技術的には が必要ですが、それは にOptional<String>
ブリッジされているからNSString*
です。ここ以外を通過する必要nil
があります。そして、技術的には you を返しますがOptional<AnyObject>
、それは にブリッジされているためid
です。そうではないことを約束しますnil
。