В справочном разделе Apple docs есть много примеров такого рода:
func runAction(_
action
: SKAction!)
Objective-C 'эквивалент' этого:
- (void)runAction:(SKAction *)
action
Мне кажется, что, вероятно, важно, чтобы (в ссылке Swift) пробел после подчеркивания и "действие" было написано курсивом.
Но я не могу понять, что это пытается передать. Так что, может быть, вопрос в том, есть... есть ссылка на соглашения, используемые в ссылках?
- здесь страница, на которую я ссылаюсь в этой ссылке на использование подчеркивания: https://developer.apple.com/documentation/spritekit/sknode#//apple_ref/occ/instm/SKNode/runAction
Swift 3 внесла некоторые изменения в то, как используются имена и имена параметров функции и метода, а также имена названий. Это имеет последствия для этого вопроса и его ответа. @Rickster делает удивительную работу, отвечая на другой вопрос о _underscores в функциях, которые очищают большую часть этого, здесь: Почему мне нужны символы подчеркивания в быстром?
Оба ответа были правильными, но я хочу уточнить немного больше.
_
используется для изменять поведение имени внешнего параметра для методов.
В разделе в разделе "Локальные и внешние параметры имен методов" в документации говорится:
Swift дает имя первого параметра в методе имя локального параметра по умолчанию и дает по умолчанию второй и последующие имена параметров как локальные, так и внешние имена параметров.
С другой стороны, функции по умолчанию не имеют внешних имен параметров.
Например, у нас есть этот метод foo()
, определенный в классе Bar
:
class Bar{
func foo(s1: String, s2: String) -> String {
return s1 + s2;
}
}
Когда вы вызываете foo()
, он называется как bar.foo("Hello", s2: "World")
.
Но вы можете переопределить это поведение, используя _
перед s2
, где он был объявлен.
func foo(s1: String, _ s2: String) -> String{
return s1 + s2;
}
Затем, когда вы вызываете foo
, его можно просто вызвать как bar.foo("Hello", "World")
без имени второго параметра.
Вернемся к вашему случаю, runAction
- это метод, потому что он связан с типом SKNode
, очевидно. Таким образом, добавление параметра _
до параметра action
позволяет вызывать runAction
без внешнего имени.
Обновление для Swift 2.0
Функция и метод теперь работают одинаково в терминах объявления локального и внешнего аргументов.
Теперь функции вызывается с использованием внешнего имени параметра по умолчанию, начиная со второго параметра. Это правило применяется только к чистому коду Swift.
Итак, предоставляя _
перед функцией , вызывающему абоненту не нужно указывать имя внешнего параметра, точно так же, как вы бы сделали для метода .
_
напишите перед вторым параметром, ваш ответ достаточно ясен; что если в func runAction(_action: SKAction!)
, _
стоит перед первым параметром или если вы напишите следующий код, то func foo(_ s1: String) { // your code }
Xcode выдаст вам предупреждение, но есть много кода, как func bringSubviewToFront(_ view: UIView)
в ссылке, почему?
Подчеркивание - это общий токен, используемый для указания отброшенного значения.
В этом конкретном случае это означает, что функция будет вызываться как runAction(argument)
вместо runAction(action:argument)
В других контекстах он имеет другое сходное значение, например. в:
for _ in 0..<5 { ... }
Это означает, что мы просто хотим выполнить блок 5 раз, и нам не нужен индекс внутри блока.
В этом контексте:
let (result, _) = someFunctionThatReturnsATuple()
Это означает, что нам все равно, что второй элемент кортежа, только первый.
Идентификатор перед объявлением параметра определяет имя внешнего параметра. Это имя, которое должно быть предоставлено вызывающим абонентом при вызове функции:
func someFunction(externalParameterName localParameterName: Int)
Swift предоставляет автоматическое внешнее имя для любого дефолтного параметра, который вы определяете, если вы не предоставляете внешнее имя самостоятельно. Использование подчеркивания для внешнего имени параметра отказывается от этого поведения:
Вы можете отказаться от этого поведения, написав символ подчеркивания (
_
) вместо явного внешнего имени при определении параметра.
Подробнее об этом поведении читайте в разделе "Внешние имена для параметров со значениями по умолчанию здесь.
SK
не хотят, чтобы вы дважды писали action
, потому что «action» уже является частью имени функции. Другими словами, они не хотят, чтобы вы писали sprite.runAction(action:moveGroundSpritesForever)
. Цель внешних имен параметров состояла в том, чтобы сделать ваш код «читаемым как предложение»; использование action
дважды нанесло бы ущерб цели этого.
Так как Swift 3 все метки меток требуются по умолчанию.
Вы можете заставить среду IDE скрыть метку аргумента с помощью _
.
func foo(a: String) {
}
func foo2(_ a: String) {
}
называется foo(a: "abc")
и foo2("abc")
Примечание.. Это можно использовать только тогда, когда
a
является (внешним) символом аргумента и (внутренним) именем переменной одновременно. Он эквивалентен -func foo(a a: String)
не принимает_
.
Вы можете видеть, что Apple использует его через API. Библиотеки Apple по-прежнему записываются в формате Objective-C (если нет, они имеют одинаковые имена функций, которые были разработаны для синтаксиса Objective-C)
Такие функции, как applicationWillResignActive(_ application: UIApplication)
, имеют избыточное имя параметра application
, так как в нем есть имя приложения.
func runAction(_ action: SKAction!)
будет называться без _
, как runAction(action:)
.
Имя параметра action
будет избыточным, поскольку в имени функции уже есть один. Это цель и почему она там.
Я думаю, что это принуждает соглашение в Swift, что делает его ближе к objective-c, что лучше соответствует соглашениям cocoa. В objc вы не (внешне) назовите свой первый параметр. Вместо этого, по соглашению, вы обычно включаете внешнее имя в последней части имени метода следующим образом:
- (void)myFancyMethodWithFirstName:(NSString *)aFirstName lastName:(NSString *)aLastName;
[someInstance myFancyMethodWithFirstName:@"John" lastName:@"Doe"];
Чтобы сделать вызовы Swift api совместимыми с objc, вы захотите подавить имя внешнего параметра первого параметра.
func myFancyMethodWithFirstName(_ firstName:String, lastName:String);
someInstance.myFancyMethodWithFirstName("John", lastName:"Doe")
На самом деле существует разница между реальным кодом, используемым для определения метода и объявления метода в документах Apple. Возьмем UIControl - addTarget: действие: forControlEvents: метод, например, настоящий код:
Но в документах это выглядит так (уведомление _ перед мишенью):
В реальном коде _ используется для создания второго или последующего параметра внешнего имени не появляется при вызове метода, а в документах _ перед локальным именем параметра указывает, что при вызове метода или функции вы не должны указывать внешнее имя.
Нет внешнего имени, если функция вызывается по умолчанию, если вы не указали свой собственный или не добавили # перед (без пробела) локальное имя параметра, например, так мы используем dispatch_after:
И в документах это выглядит так (обратите внимание на три _):
Согласование объявления функции является таким же, как я описал для метода.
Просто визуально.
Как вы можете видеть, _
просто опустить имя локального параметра или нет.