web-dev-qa-db-ja.com

Xcode 8:関数型には、ビルドを壊す引数ラベルを含めることはできません

何らかの理由でSwiftは、ユーザーに完了ハンドラーのパラメーターラベルを削除するように強制することで、コーディングを読みにくくすることを選択したようです。私はSwiftの議論を読みましたが、それでも間違いだと思います。少なくとも彼らはそれをオプションにしたかもしれません。

Xcode 8を使用してビルドする場合、コンパイラーにSwift 2.3を使用するように強制する方法はありますか。これらのエラーはもう発生しませんか?レガシーSwift(ビルド設定の下)を使用するオプションを更新しました legacy support in xcode しかし、私はまだこのエラーを受け取っているようです:

関数タイプに引数ラベル「isloggedIn」を含めることはできません。代わりに「_」を使用してください

error Xcode 8

完了ハンドラーでラベルを保持するにはどうすればよいですか?

71
UKDataGeek

Swiftデザイナーは、関数型の引数ラベルを禁止することを決定しました。

理由をここで説明します: https://github.com/Apple/Swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md

引数ラベルを禁止すると、クロージャを誤って呼び出すことがはるかに簡単になり、言語の型システムを単純化するよりも重要だと思われるため、これはイライラし疑わしい選択です。

ユーザビリティ>イデオロギー。

93
Crashalot

考慮すべき回避策。できません:

func doStuff(completion: (foo: Int, bar: String) -> Void) {
    ...
    completion(foo: 0, bar: "")
}

...しかし、あなたはできる:

func doStuff(completion: ((foo: Int, bar: String)) -> Void) {
    ...
    completion((foo: 0, bar: ""))
}

つまり、タプルであるクロージャーへの単一の名前のない引数、この場合は(foo: Int, bar: String)を持っています。

それ自体はいですが、少なくとも引数のラベルは保持します。

免責事項:このアプローチのキャプチャまたはパフォーマンスへの影響については考えていません。

21
sam-w

上記の情報に基づいて-これを実際に修正し、そのパフォーマンスを確保する唯一の方法は、次の目的で引数ラベルをオプションにするという提案を上げることであるように見えます:

  1. 開発の速度を改善します(引数ラベルなしでは、完了ハンドラーを配置するたびにメソッドの最上部までスクロールする必要があります。
  2. エラーの削減:(特にブール値を期待するもので、不正な完了ハンドラエントリが原因でいくつかのエラーが発生しました)
  3. チームメンバー間でコードを読みやすくします。すべての人がチームメンバーを1人しか持っていないため、他の人のコードを簡単に取得できることが必要です。
  4. 最後に、優れたプログラミングの実践とは、ソリューションが開発中の実際のアイテムと同じように見えることを意味します。 completionhandler: (newvalues, nil)は、completionhandler(results: newValue, error:nil)より管理対象のアイテムのように見えません

私はこれを読んでいる人々が私がそれを提出する前にこれに関する彼らのフィードバック/コメントを共有することを望みます。

編集:私はここにピッチを提出しました: https://lists.Swift.org/pipermail/Swift-evolution/Week-of-Mon-20161010/028083.html 同意されたようですそれが起こるように見えますが、議論はこれがSwift 4の改善として提出されるかどうかです(非常に可能性が高い)

10
UKDataGeek

_を使用してパラメーターに名前を付けないようにする必要がありますが、それは残念です。各パラメーターに_を付けて、関数を盲目的に呼び出す代わりに、ラッパーオブジェクトを作成することをお勧めします。

関数型の名前付きパラメーターを失うと、間違った値で関数を呼び出すリスクが増えるため、構造体でパラメーターをラップし、それを関数の唯一のパラメーターにすることをお勧めします。

これにより、構造体のフィールドに名前が付けられ、関数に渡す値のタイプは1つだけになります。関数のパラメーターに名前を付けることができた場合よりも面倒ですが、できません。少なくともこの方法では、より安全になり、汚れが少なくなります。

struct LineNoteCellState {

    var lineNoteText: String?
    var printOnInvoice = false
    var printOnLabel = false
}

使用例は次のとおりです。

cell.configure(editCallback: { (_ state: LineNoteCellState) in

    self.lineNoteText = state.lineNoteText
    self.printOnInvoice = state.printOnInvoice
    self.printOnLabel = state.printOnLabel
})
9

半回避策、_に注意してください

completion: (_ success: Bool) -> Void
4
Maciej Swic