Xcode 8: типи функцій не можуть мітити аргументи, що порушують мою збірку


74

Здається, чомусь Swift вирішили зробити кодування в ньому менш читабельним, змусивши користувачів видаляти мітки параметрів обробника завершення. Я прочитав обговорення Swift і досі вважаю, що це помилка. Принаймні вони могли б зробити це необов’язковим.

При побудові за допомогою Xcode 8 - чи є спосіб змусити компілятор використовувати Swift 2.3, щоб я більше не отримував цих помилок? Я оновив можливість використовувати застарілий Swift (під налаштуваннями збірки), застаріла підтримка в xcode але, схоже, я все ще отримую цю помилку:

Типи функцій не можуть мітити аргумент 'isloggedIn'; використовуйте замість "_"

помилка Xcode 8

Як я можу зберігати свої мітки в обробниках завершення?


Схоже, це просто каже, що ви не можете мати параметр з назвою "помилка", не те, що ви не можете дати йому ім'я. Ви пробували перейменувати "помилку" на щось інше?
dudeman

23
@dudeman Swift 3 явно забороняє використовувати мітки аргументів у типах функцій. Сумнівний вибір, дуже розчаровує.
Крашалот

17
Засмучує і дратує. Я вириваю хороший код, щоб зробити його менш читабельним і схильним до помилок
UKDataGeek,

13
Я абсолютно ненавиджу цю зміну.
UKDataGeek

5
Здається, Swift 3 намагається бути надто філософськи бездоганним, і історія людства говорить нам, що це не найефективніший спосіб робити щось. Абсолютно ненавиджу багато змін у Swift 3
funct7

Відповіді:


99

Дизайнери Swift вирішили заборонити мітки аргументів для типів функцій.

Аргументи пояснюються тут: https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md

Це невтішний і сумнівний вибір, оскільки заборона міток аргументів значно полегшує неправильне посилання на закриття, що здається важливішим, ніж спрощення системи типу мови.

Юзабіліті> ідеологія.


6
Я з цим погоджуюсь - але це насправді не рішення. Я запропоную нам попрацювати над тим, щоб внести пропозицію, щоб потенційно зробити це необов’язковим.
UKDataGeek

Додали це як поточне рішення, як справді добре пояснене
UKDataGeek

16
Досі немає ознак рішення, яке я запропонував у Swift 3.1 - ось сподіваємось, ми отримаємо його до swift 4 .. дуже ненавиджу цю зміну !!
UKDataGeek

@Crashalot Але як же можна отримати аргументи, передані через ці функції ?!
MatterGoal

@matterGoal що ти маєш на увазі?
UKDataGeek

23

Обхідний шлях для розгляду. Ви не можете зробити:

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).

Це по-своєму потворно, але принаймні ви зберігаєте мітки аргументів.


1
будь-яка ідея, як зробити цю роботу з загальнодоступними typealias typealias ImageDataCompletion = ((((imgData imgData: Data ?, _ err: MYGR8TErrorClass?)) -> Void) дає: ... Елемент кортежу не може мати дві мітки !!!! wtf ????
Антон Тропашко

@AntonTropashko: (((imgData imgData: Data?, _ err: MYGR8TErrorClass?)) -> Void)повинно бути (((imgData: Data?, err: MYGR8TErrorClass?)) -> Void). Ви намагаєтеся двічі позначити елементи кортежу
сам-вт

2
Обмеженням цього рішення є те, що кортежі не можуть мати єдине значення.
Марк

11

Виходячи з наведеної вище інформації, виявляється, що єдиним способом по-справжньому це виправити та забезпечити його ефективність є висунення пропозиції зробити ярлики аргументів необов’язковими з метою:

  1. покращення швидкості розробки (без міток аргументів нам потрібно прокручувати угору методу кожного разу, коли ми вводимо обробник завершення.
  2. Зменшити кількість помилок: (У мене вже було кілька помилок, спричинених неправильними записами обробника завершення, особливо з тими, які очікують логічні значення)
  3. Зробіть код більш читабельним для членів команди. Не кожен має лише одного члена команди, і тому можливість легко підібрати код інших людей є обов’язковою умовою.
  4. Нарешті, хороша практика програмування означає, що рішення повинно виглядати так само, як фактичний елемент, що розробляється. completionhandler: (newvalues, nil)виглядає менше як елемент, яким управляють, ніжcompletionhandler(results: newValue, error:nil)

Я хотів би, щоб люди, які читають це, поділились своїми відгуками / коментарями щодо цього нижче, перш ніж подавати його, щоб я міг показати, що є інші, хто підтримує це.

Редагувати: Я подав сюжет тут: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161010/028083.html, який, здається, був узгоджений. Схоже, це відбудеться, проте дискусія полягає в тому, чи подається це як покращення Swift 4 (дуже ймовірно)


2
Гаразд, оскільки ви просили про це, дозвольте мені випустити: це не буде перший раз, коли мавпи з відкритим джерелом щось накрутили (можна до їх цінного внеску). Амінь.
Антон Тропашко

@AntonTropashko голос за випуск через переповнення стека - сподіваюся, вам буде краще ??
UKDataGeek

також проголосував за відповідь! яке полегшення! серйозно: ні
Антон Тропашко

@MobileBloke який статус цього? Я не бачу, що це потрапило в мову ...
frangulyan

Ні - схоже, його деприорітизували. Це все ще так дратує.
UKDataGeek

9

Вам потрібно використовувати _, щоб зробити ваші параметри безіменними, і це прикро. Замість того, щоб приєднувати _ до кожного параметра, а потім сліпо викликати вашу функцію, я б запропонував зробити об'єкт-обгортку.

Оскільки втрата іменованих параметрів для типів функцій створює більший ризик того, що ви викликатимете функцію з неправильними значеннями, я б запропонував обернути параметри в структуру і мати це єдиний параметр для вашої функції.

Таким чином поля вашої структури називаються, і існує лише один тип значень, який потрібно передати у вашу функцію. Це більш громіздко, ніж якби ми змогли назвати параметри функції, але ми не можемо. Принаймні таким чином ви будете в безпеці і почуватиметесь менш брудно.

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
})

4

Напіввихідне рішення, зверніть увагу на _

completion: (_ success: Bool) -> Void

1
Здається, це не самозавершення для мене - яка функція підкреслення перед параметром успіху?
UKDataGeek
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.