Свифт: варианты тестирования по нолям


я использую 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 106

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" {

}

конечно, это не так читаемо, как некоторые из других предложенных сообщений, но получает работу и несколько сжато, чем другие предлагаемые решения.