Как вы разворачиваете опционы Swift?

Как правильно развернуть как обычные, так и неявные опции?

Кажется, в этой теме есть путаница, и я просто хотел бы получить справку обо всех способах и их полезности.

В настоящее время существует два способа создания опций:

var optionalString: String?

var implicitOptionalString: String!

Каковы все способы развернуть оба? Кроме того, в чем разница между использованием ! а также ? во время распаковки?

8 ответов

Решение

Есть много сходств и просто несколько различий.

(Обычный) Опционально

  • Декларация: var opt: Type?

  • Небезопасная распаковка: let x = opt!.property // error if opt is nil

  • Безопасно проверяя наличие: if opt != nil { ... someFunc(opt!) ... } // no error

  • Безопасное распаковывание через привязку: if let x = opt { ... someFunc(x) ... } // no error

  • Безопасное сцепление: var x = opt?.property // x is also Optional, by extension

  • Безопасное объединение нулевых значений: var x = opt ?? nonOpt

Неявно развернутые необязательные

  • Декларация: var opt: Type!

  • Небезопасное развертывание (неявное): let x = opt.property // error if opt is nil

    • Небезопасная распаковка через назначение:
      let nonOpt: Type = opt // error if opt is nil

    • Небезопасная распаковка через передачу параметров:
      func someFunc(nonOpt: Type) ... someFunc(opt) // error if opt is nil

  • Безопасно проверяя наличие: if opt != nil { ... someFunc(opt) ... } // no error

  • Безопасное сцепление: var x = opt?.property // x is also Optional, by extension

  • Безопасное объединение нулевых значений: var x = opt ?? nonOpt

Начиная с бета-версии 5 у нас также есть новый оператор объединения (??):

var a : Int?
let b : Int = a ?? 0

Если необязательный параметр!= Nil, он разворачивается, иначе используется значение справа от оператора.

Я создал подход, чтобы развернуть необязательное значение:

// MARK: - Modules
import Foundation
import UIKit
import CoreData

// MARK: - PROTOCOL
protocol OptionalType { init() }

// MARK: - EXTENSIONS
extension String: OptionalType {}
extension Int: OptionalType {}
extension Double: OptionalType {}
extension Bool: OptionalType {}
extension Float: OptionalType {}
extension CGFloat: OptionalType {}
extension CGRect: OptionalType {}
extension UIImage: OptionalType {}
extension IndexPath: OptionalType {}
extension Date: OptionalType {}
extension UIFont: OptionalType {}
extension UIColor: OptionalType {}
extension UIViewController: OptionalType {}
extension UIView: OptionalType {}
extension NSMutableDictionary: OptionalType {}
extension NSMutableArray: OptionalType {}
extension NSMutableSet: OptionalType {}
extension NSEntityDescription: OptionalType {}
extension Int64: OptionalType {}
extension CGPoint: OptionalType {}
extension Data: OptionalType {}
extension NSManagedObjectContext: OptionalType {}

prefix operator ?*

//unwrapping values
prefix func ?*<T: OptionalType>( value: T?) -> T {
    guard let validValue = value else { return T() }
    return validValue
}

Вы также можете добавить свой собственный тип данных.

Использование:-

var myString = ?*str

Надеюсь, поможет:)

Необязательный тип означает, что переменная может быть nil.

Пример:

var myString: Int? = 55
myString = nil

Знак вопроса указывает, что он может иметь нулевое значение.

Но если вы заявите, как это:

var myString : Int = 55
myString = nil

Это покажет ошибку.

Теперь, чтобы получить значение, вам нужно развернуть его:

print(myString!)

Но если вы хотите, чтобы развернуть автоматически:

var myString: Int! = 55

Затем:

print(myString)

Не нужно разворачивать. Надеюсь, это поможет.

Безопасное развертывание опций в Swift 5.7 ⛑

Различные техники (в порядке предпочтения)

Используйте правильный инструмент для работы:

  1. Необязательная цепочка
  2. Операторы объединения Nil

В Swift есть много способов безопасно развернуть необязательные значения. Мои причины для заказа техники в моих предпочтениях выше:

  1. Мы должны разворачивать опции только в том случае, если нам это действительно нужно. В этом случае нам не нужно разворачивать его и можно использовать дополнительную цепочку. напримерlet value = optional?.value
  2. Защитные операторы полезны для раннего выхода из потока, когда есть предварительное условие. Во многих случаях это самое чистое решение за счет снижения уровня вложенности.
  3. может быть более удобочитаемым для последовательной логики. В некоторых случаях более удобочитаем, чем s, когда мы не хотим выходить из функции, а продолжаем использовать дополнительную логику за пределами блока развертывания. является гибким и может также использоваться с аналогичным синтаксисом, как операторы.
  4. Мы можем использовать несколько защитных операторов, чтобы развернуть несколько необязательных параметров перед их использованием, или даже использовать,,&&или||для проверки нескольких условных выражений в одном файле .
  5. Операторы объединения Nil хорошо работают, чтобы аккуратно развернуть необязательные параметры со значением по умолчанию:??. Однако не злоупотребляйте ими, потому что с помощью часто проще выйти раньше.
  6. Я описал улучшенный синтаксис для иguard let(намного чище в Swift 5.7).
  7. Принудительная развертка или IUO (неявные необработанные опции) могут привести к сбоям во время выполнения. Они обозначены значком!и являются анти-шаблоном в iOS, если только они не являются частью набора тестов, потому что они могут привести к сбою, если необязательныйnil. В этом случае мы не используем улучшенную систему типов Swift по сравнению с Objective-C. В тестах мы не заботимся о чистоте кода, потому что тесты не будут работать в продакшене, а их назначение скрыто.

Новый синтаксис дляif letиguard

      var x: EnumExample?

if let x {
   print(x.rawValue) // No longer optional
}

// We can still explicitly name the `if let` value if we want.
if let value = x {
    print(value.rawValue)
}

guard let x else {
    return
}
print(x.rawValue) // No longer optional

guard let value = x else {
    return
}
print(value.rawValue)

print(x?.rawValue ?? 0) // Unwrap with nil coalescing

ПРИМЕЧАНИЕ. Я также нахожу опциональную цепочку чистой альтернативой разворачиванию опционов и использованию x != nilдостаточно для случаев, когда нам нужно только проверить существование. Однако это выходит за рамки вопроса о разворачивании опций.

      There is only seven ways to unwrap an optional in Swift

    var x : String? = "Test"
1,Forced unwrapping — unsafe.

    let a:String = x!
2,Implicitly unwrapped variable declaration — unsafe in many cases.

    var a = x!
3,Optional binding — safe.
if let a = x {
  print("x was successfully unwrapped and is = \(a)")
  }
4,Optional chaining — safe.

    let a = x?.count
5,Nil coalescing operator — safe.

    let a = x ?? ""
6,Guard statement — safe.

    guard let a = x else {
  return
}
7,Optional pattern — safe.

    if case let a? = x {
  print(a)
}

Вы также можете создавать расширения для определенного типа и безопасно разворачивать их со значением по умолчанию. Для того же я сделал следующее:

extension Optional where Wrapped == String {
    func unwrapSafely() -> String {
        if let value = self {
            return value
        }
        return ""
    }
}

Пример кода безопасного развертывания с использованием привязки:

      let accountNumber = account.accountNumber //optional
let accountBsb = account.branchCode //optional
var accountDetails: String = "" //non-optional

if let bsbString = account.branchCode, let accString = account.accountNumber {
    accountDetails = "\(bsbString) \(accString)" //non-optional
}
Другие вопросы по тегам