Xcode 8 / Swift 3:「タイプUIViewControllerの式?未使用」の警告


230

私は以前にきれいにコンパイルした次の関数を持っていますが、Xcode 8で警告を生成します。

func exitViewController()
{
    navigationController?.popViewController(animated: true)
}

「タイプ「UIViewController?」の式は使用されていません。」

なぜこれが表示され、それを削除する方法があるのですか?

コードは期待どおりに実行されます。

回答:


498

TL; DR

popViewController(animated:)が返されUIViewController?、値を取得していないため、コンパイラが警告を出します。解決策はそれをアンダースコアに割り当てることです:

_ = navigationController?.popViewController(animated: true)

Swift 3の変更

Swift 3以前は、すべてのメソッドにデフォルトで「破棄可能な結果」がありました。メソッドが返したものをキャプチャしなかった場合、警告は発生しません。

結果をキャプチャする必要があることをコンパイラに伝えるには@warn_unused_result、メソッド宣言の前に追加する必要がありました。これは、変更可能な形式(例:sortおよびsortInPlace)を持つメソッドに使用されます。@warn_unused_result(mutable_variant="mutableMethodHere")コンパイラに知らせるために追加します。

ただし、Swift 3では動作が逆になります。すべてのメソッドが、戻り値がキャプチャされないことを警告するようになりました。警告が必要ないことをコンパイラーに伝えたい場合は@discardableResult、メソッド宣言の前に追加します。

戻り値を使用したくない場合は、アンダースコアに割り当てて、コンパイラに明示的に通知する必要があります。

_ = someMethodThatReturnsSomething()

これをSwift 3に追加する動機:

  • sort考えられるバグの防止(例:コレクションを変更するという考え方を使用)
  • 他の協力者のために結果をキャプチャしない、または結果をキャプチャする必要があるという明示的な意図

UIKit APIはこれに遅れをとっており、戻り値を取得せずに@discardableResult(通常ではないにしても)完全に通常の使用を追加していませんpopViewController(animated:)

続きを読む


15
これは(私の意見では)間違いなくSwift 2から一歩離れたものであり、特にこのようなメソッドがある場合、それら値を返しますが、使用しないだけの完全に有効なユースケースがあります。
Nicolas Miari

15
1.必要はありません。let前にletorを付けずに、_に割り当てることができますvar
リクスター

1
@ricksterそれが答えに追加されることを知りませんでした。
tktsubota 2016年

5
2. @NicolasMiari バグを報告してください。@discardableResult値を返す関数には注釈()がありますが、戻り値を無視することが期待される場所にあります。UIKitはそのアノテーションをAPIに適用していません。
リクスター

37
これは恐ろしい構文です。なぜ彼らはこれをするのでしょうか?ああ。
デビッドS.

38

人生があなたにレモンを与えるとき、拡張を行います:

import UIKit

extension UINavigationController {
    func pop(animated: Bool) {
        _ = self.popViewController(animated: animated)
    }

    func popToRoot(animated: Bool) {
        _ = self.popToRootViewController(animated: animated)
    }
}

ようなものを追加@discardableResult func pop(animated: Bool) -> UIViewController?すると、回避しようとしているのと同じ警告が表示されることに注意してください。

拡張機能を使用すると、次のように記述できます。

func exitViewController()
{
    navigationController?.pop(animated: true)
}

func popToTheRootOfNav() {
    navigationController?.popToRoot(animated: true)
}

編集:popToRootも追加されました。


これは、Xcodeの更新で確実に修正されるものに対する最もクリーンな修正であるため、受け入れられる解決策になるはずです。
フィリップブロードウェイ

24

Swift 3では、宣言された戻り値を持つ関数の戻り値を無視すると警告が発生します。

これをオプトアウトする1つの方法は、@discardableResult属性で関数をマークすることです。この機能を制御できないため、機能しません。

警告を取り除くもう1つの方法は、に値を割り当てることです_。これは、メソッドが値を返すことを知っているが、それをメモリに保持したくないことをコンパイラに伝えます。

let _ = navigationController?.popViewController(animated: true)

2
_AppleがUIKitをこの新しい属性で更新するまで、醜いものに固執する必要があると思います。
Nicolas Miari

2
残念ながら@discardableResult機能しません(少なくとも8b4でまだ鳴きます)。フリードリッヒシラーは腐ったリンゴを愛していました。おそらく好みの問題でしょう:-(
qwerty_so

5

スクリーンショット1

それwork correctly if kept as it isだけどnumber of warning increases.

replace it with underscore ( _ )醜いようですが、解決策は単純です。

Eg.  _ = navigationController?.popViewController(animated: true)

スクリーンショット2


2

この状態でdiscardableResultを使用します。

<Swift Programming Language>によると、「言語リファレンス-属性」の章。

discardableResult

この属性を関数またはメソッド宣言に適用して、結果を使用せずに値を返す関数またはメソッドが呼び出された場合のコンパイラ警告を抑制します。

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Attributes.html#//apple_ref/doc/uid/TP40014097-CH35-ID347

<Swift Programming Language>のデモ、「言語ガイド-メソッド」の章もあります。

@discardableResult
    mutating func advance(to level: Int) -> Bool {
    ...
return true
}

戻り値を無視するためにadvance(to :)メソッドを呼び出すコードは必ずしも間違いではないため、この関数は@discardableResult属性でマークされています。この属性の詳細については、属性を参照してください。

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Methods.html#//apple_ref/doc/uid/TP40014097-CH15-ID234


0

CodeReaperの回答のような拡張機能を利用したい場合は、を使用してください@descardableResult。これにより、すべての可能性が保持されますが、警告は表示されなくなります。

import UIKit

extension UINavigationController {
    @discardableResult func pop(animated: Bool) -> UIViewController? {
        return self.popViewController(animated: animated)
    }

    @discardableResult func popToRoot(animated: Bool) -> [UIViewController]? {
        return self.popToRootViewController(animated: animated)
    }
}

-1

もう1つの方法は、self.navigationController?値をラップ解除してpopViewController関数を呼び出すことです。

    if let navigationController = navigationController {
        navigationController.popViewController(animated: true)
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.