Свифт: варианты тестирования по нолям
я использую Xcode 6 Beta 4. У меня есть эта странная ситуация, когда я не могу понять, как правильно проверить варианты.
если у меня есть дополнительный xyz, это правильный способ проверить:
if (xyz) // Do something
или
if (xyz != nil) // Do something
документы говорят, чтобы сделать это первым способом, но я обнаружил, что иногда требуется второй способ и не генерирует ошибку компилятора, но в других случаях второй способ генерирует ошибку компилятора.
мой конкретный пример использует синтаксический анализатор GData XML, подключенный к swift:
let xml = GDataXMLDocument(
XMLString: responseBody,
options: 0,
error: &xmlError);
if (xmlError != nil)
вот, если бы я только сделал:
if xmlError
Он всегда будет возвращать true. Однако, если я это сделаю:
if (xmlError != nil)
тогда это работает (как это работает в Objective-C).
есть ли что-то с GData XML и то, как он обрабатывает optionals, которые мне не хватает?
11 ответов:
в Xcode beta 5, они больше не позволяют вам делать
var xyz : NSString? if xyz { //Do Something }
выдает ошибку
"does not conform to protocol 'BooleanType.Protocol'"
вы должны сделать одно из этих утверждений:
if xyz != nil { //Do Something } if let xy = xyz { //Do Something }
один из самых прямых способов использования optionals заключается в следующем:
предполагая, что
xyz
имеет необязательный тип, напримерInt?
например.if let possXYZ = xyz { // do something with possXYZ (the unwrapped value of xyz) } else { // do something now that we know xyz is .None }
таким образом, вы можете одновременно проверить, если
xyz
содержит значение, и если это так, то сразу же работать с этим значением.что касается ошибки компилятора, тип
UInt8
это не обязательно (обратите внимание, нет?') и поэтому не может быть преобразован вnil
. Убедитесь, что переменная, с которой вы работаете, является необязательной рассматривать его как таковой.
чтобы добавить к другим ответам, вместо присвоения переменной с другим именем внутри
if
состояние:var a: Int? = 5 if let b = a { // do something }
вы можете использовать одно и то же имя переменной следующим образом:
var a: Int? = 5 if let a = a { // do something }
Это может помочь вам избежать творческого имена переменных...
этим пользуется переменной тенизации это поддерживается в Swift.
от быстрого программирования руководство
если заявления и принудительное разворачивание
вы можете использовать оператор if, чтобы узнать, содержит ли дополнительный значение. Если необязательный параметр имеет значение, то он принимает значение true; если он не имеет никакого значения вообще, он оценивает в false.
так что лучший способ сделать это -
// swift > 3 if xyz != nil {}
если вы используете
xyz
в операторе if.Чем вы можете развернитеxyz
в случае, если заявление в постоянной переменной .Так что вам не нужно, чтобы развернуть каждое место в случае, если заявление, где есть.if let yourConstant = xyz{ //use youtConstant you do not need to unwrap `xyz` }
это соглашение предлагается
apple
и за ним последуют девлоперы.
Swift 3.0, 4.0
есть в основном два способа проверки необязательно к нулю. Вот примеры со сравнением между ними
1. если да
if let
Это самый простой способ проверить необязательно для nil. К этой нулевой проверке можно добавить другие условия, разделенные запятой. Переменная не должна быть равна нулю, чтобы перейти к следующему условию. Если требуется только нулевая проверка, удалите дополнительные условия в следующем код.кроме этого, если
x
не равно нулю, если закрытие будет выполнено иx_val
будет доступен внутри. В противном случае срабатывает закрытие else.if let x_val = x, x_val > 5 { //x_val available on this scope } else { }
2. охранник пусть
guard let
можно делать подобные вещи. Его основная цель - сделать его логически более разумным. Это все равно что сказать убедитесь, что переменная не равна нулю, иначе остановите функцию.guard let
смогите также сделать дополнительное условие проверяя какif let
.разница в том, что развернутое значение будет доступно в той же области, что и
guard let
, как показано в комментарии ниже. Это также приводит к тому, что при закрытии else программа должна выйти из текущей области, поreturn
,break
и т. д.guard let x_val = x, x_val > 5 else { return } //x_val available on this scope
хотя вы все равно должны либо явно сравнить необязательный с
nil
или используйте необязательную привязку для дополнительного извлечения ее значения (т. е. optionals не обязательно преобразуются в логические значения), стоит отметить, что Swift 2 добавилguard
сообщении чтобы избежать пирамида судьбы при работе с несколькими дополнительными значениями.другими словами, ваши параметры теперь включают явную проверку
nil
:if xyz != nil { // Do something with xyz }
дополнительно связывать:
if let xyz = xyz { // Do something with xyz // (Note that we can reuse the same variable name) }
и
guard
отчетность:guard let xyz = xyz else { // Handle failure and then exit this code block // e.g. by calling return, break, continue, or throw return } // Do something with xyz, which is now guaranteed to be non-nil
обратите внимание, как обычная необязательная привязка может привести к большему отступу, когда есть более одного необязательного значения:
if let abc = abc { if let xyz = xyz { // Do something with abc and xyz } }
вы можете избежать этого вложения с
guard
отчетность:guard let abc = abc else { // Handle failure and then exit this code block return } guard let xyz = xyz else { // Handle failure and then exit this code block return } // Do something with abc and xyz
вместо
if
, тернарный оператор может пригодиться, когда вы хотите получить значение, основанное на том, что что-то пропустит:func f(x: String?) -> String { return x == nil ? "empty" : "non-empty" }
другой подход, кроме использования
if
илиguard
операторы для выполнения необязательной привязки-это расширениеOptional
С:extension Optional { func ifValue(_ valueHandler: (Wrapped) -> Void) { switch self { case .some(let wrapped): valueHandler(wrapped) default: break } } }
ifValue
получает закрытие и вызывает его со значением в качестве аргумента, когда необязательный не равен нулю. Он используется таким образом:var helloString: String? = "Hello, World!" helloString.ifValue { print() // prints "Hello, World!" } helloString = nil helloString.ifValue { print() // This code never runs }
вы, вероятно, должны использовать
if
илиguard
однако, поскольку это самые обычные (таким образом, знакомые) подходы, используемые программистами Swift.
var xyz : NSDictionary? // case 1: xyz = ["1":"one"] // case 2: (empty dictionary) xyz = NSDictionary() // case 3: do nothing if xyz { NSLog("xyz is not nil.") } else { NSLog("xyz is nil.") }
этот тест работает, как ожидалось во всех случаях. Кстати, вам не нужны скобки
()
.
теперь вы можете сделать в swift следующее, что позволяет вам восстановить немного цели-c
if nil else
if textfieldDate.text?.isEmpty ?? true { }
Если у вас есть условное и вы хотите развернуть и сравнить, как насчет использования преимущества оценки короткого замыкания составного булева выражения, как в
if xyz != nil && xyz! == "some non-nil value" { }
конечно, это не так читаемо, как некоторые из других предложенных сообщений, но получает работу и несколько сжато, чем другие предлагаемые решения.