Як вирішити “Інтерполяція рядків створює опис налагодження для необов’язкового значення; Ви мали намір це чітко сказати? " у бета-версії Xcode 8.3?


87

Починаючи з бета-версії 8.3, zillions попереджає: "Інтерполяція рядків створює опис налагодження для необов’язкового значення; ви мали намір зробити це явним?" з'явився в моєму коді.

Наприклад, попередження вискакувало в такій ситуації, коли варіанти могли призвести до нуля:

let msg = "*** Error \(options["taskDescription"]): cannot load \(sUrl) \(error)"

Як було попередньо розроблено, для мене (і для компілятора) опціони можна було інтерполювати як "нуль". Але компілятор передумав.

Компілятор пропонує додати конструктор String із описом наступним чином:

let msg = "*** Error \(String(describing: options["taskDescription"])): cannot load \(sUrl) \(error)"

Очевидно, результати явні, але на мій погляд також дуже громіздкі. Чи є кращий варіант? Чи потрібно виправляти всі ці попередження чи краще чекати наступної бета-версії?

Знімок екрана для опису


26
Яке справді прикрий застереження ...
Джонні

Swift 3зламав своє, logі я помилився, просто використовуючи printзамість цього. Завжди слід створювати власну обгортку, інакше ця "нова функція" вас вразить.
superarts.org

Відповіді:


105

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

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

var i: Int? = 5
var d: Double? = nil

print("description of i: \(i as Int?)")    // description of i: Optional(5)
print("description of d: \(d as Double?)") // description of d: nil

Що також можна узагальнити на as Optional:

print("description of i: \(i as Optional)") // description of i: Optional(5)
print("description of d: \(d as Optional)") // description of d: nil

У Swift 5, за допомогою нової системи інтерполяції рядків, запровадженої SE-0228 , ще одним варіантом є додавання власного appendInterpolationперевантаження для DefaultStringInterpolation:

extension DefaultStringInterpolation {
  mutating func appendInterpolation<T>(optional: T?) {
    appendInterpolation(String(describing: optional))
  }
}

var i: Int? = 5
var d: Double? = nil

print("description of i: \(optional: i)") // description of i: Optional(5)
print("description of d: \(optional: d)") // description of d: nil

І, за бажанням, ви навіть можете видалити мітку аргументу, щоб повністю вимкнути попередження в модулі (або в певному файлі, якщо ви позначите його як fileprivate):

extension DefaultStringInterpolation {
  mutating func appendInterpolation<T>(_ optional: T?) {
    appendInterpolation(String(describing: optional))
  }
}

var i: Int? = 5
var d: Double? = nil

print("description of i: \(i)") // description of i: Optional(5)
print("description of d: \(d)") // description of d: nil

Хоча особисто я волів би зберегти мітку аргументів.


З пропозиції не зрозуміло, чи буде ця зміна постійною? Що ти думаєш? @Hamish
Stéphane de Luca

@ StéphanedeLuca У списку розсилки було досить багато обговорень щодо інших рішень, таких як дозволяючи ?? "nil"замовчувати попередження, яке, здавалося, було досить популярним, що може з’явитися в іншій пропозиції найближчим часом. Я згоден з тим, що цей обхідний шлях є менш ніж ідеальним - особисто, я вважаю, що досить очевидно очікувати, що Optional(...)його буде інтерпольовано в рядок для сильного факультативного - це було насправді лише у випадку НУО, які потребували цього попереджувального ІМО. Але Свіфт постійно розвивається, тому все це може змінитися пізніше. Але наразі це те, що ми маємо.
Хаміш,

Я також наткнувся на дещо `` пов'язану '' проблему в якщо не дозволяти більше не розпаковувати тут stackoverflow.com/questions/42543512/ ... якщо ви можете подивитися? @Hamish
Stéphane de Luca

... у кожному разі цей код - божевілля:guard result == nil else { print("result was \(result as Optional)") return }
loretoparisi

1
@loretoparisi Чому б не використовувати if let? тобто if let result = result { print("result was \(result)"); return }. Не всі дострокові повернення потрібно робити з охоронцями.
Hamish

29

Два простіших способи вирішення цього питання.

Варіант 1:

Перший - це "розгортання сили" значення, яке ви хотіли б повернути, використовуючи удар (!)

var someValue: Int? = 5
print(someValue!)

Вихід:

5

Варіант 2:

Інший спосіб, який може бути кращим - це "безпечно розгорнути" значення, яке потрібно повернути.

var someValue: Int? = 5

if let newValue = someValue {
    print(newValue)
}

Вихід:

5

Рекомендую вибрати варіант 2.

Порада: Уникайте силового розгортання (!), Де це можливо, оскільки ми не впевнені, чи завжди будемо мати значення, яке потрібно розгорнути.


1
Я новий, але мені подобається варіант 2 перевірити обгортку перед друком, і у вас завжди є можливість надрукувати щось інше, коли воно розгорнуте
AbuTaareq

16

здається, використання String (з описом: необов’язково) є найпростішим.

значення за замовчуванням ?? не має сенсу для нестрункових, наприклад Int.
Якщо Int дорівнює нулю, тоді ви хочете, щоб журнал відображав значення `` nil '' за замовчуванням для іншого Int, наприклад 0.

Код ігрового майданчика для тестування:

var optionalString : String? = nil
var optionalInt : Int? = nil

var description_ = ""
description_ = description_ + "optionalString: \(String(describing: optionalString))\r"
description_ = description_ + "   optionalInt: \(String(describing: optionalInt))\r"

print(description_)

Вихідні дані

optionalString: nil
optionalInt: nil

13

Після оновлення до Xcode 8.3 та отримання безлічі попереджувальних повідомлень, я придумав наступне, що більше нагадує оригінальну поведінку вихідних даних, що легко додається, зменшує багатослівність використання "String (описує :)" як у коді, так і на виході .

По суті, додайте необов’язкове розширення, яке дає рядок, що описує річ у додатковому, або просто «нуль», якщо не встановлено. Крім того, якщо річ у додатковому файлі є рядком, поставте його в лапки.

extension Optional {
    var orNil : String {
        if self == nil {
            return "nil"
        }
        if "\(Wrapped.self)" == "String" {
            return "\"\(self!)\""
        }
        return "\(self!)"
    }
}

І використання на дитячому майданчику:

var s : String?
var i : Int?
var d : Double?

var mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = nil    i = nil   d = nil"

d = 3
i = 5
s = ""
mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = ""    i = 5   d = 3.0"

s = "Test"
d = nil
mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = "Test"    i = 5   d = nil"

Дякуємо за допомогу за таким посиланням:

check-if-variable-is-an-optional-and-what-type-it-wraps


Це рішення не працює в додатковому ланцюжку. Подобається a?.b?.c.orNil.
Вінсент Сіт,

11

Див. Виправлення Оле Бегемана для цього . Я це люблю. Він створює ???оператор, який потім можна використовувати так:

var someValue: Int? = 5
print("The value is \(someValue ??? "unknown")")
// → "The value is 5"
someValue = nil
print("The value is \(someValue ??? "unknown")")
// → "The value is unknown"

5
Посилання на його публікацію в блозі, де це описується, було б корисним, на мою думку: oleb.net/blog/2016/12/optionals-string-interpolation
Ніколай Хенріксен

8

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

Знімок екрана додано

  1. Використовуйте String(describing:)для мовчання цього попередження:

    Використовуючи це, це стане String(describing:<Variable>)

    Напр. :String(describing: employeeName)

  2. Введіть, default valueщоб уникнути цього попередження:

    Використовуючи це, це стане (<Variable> ?? default value)

    Наприклад: employeeName ?? “Anonymous” as! String


1
Так, я б також пішов за оператором Nil-Coalescing: developer.apple.com/library/content/documentation/Swift/…
kevinius

1
Чудова відповідь! Nil-coalescing добре працює з цим, якщо у вас є альтернативне значення рядка
Lance Samaria

1

Стрімкий 5

Моє рішення вносить extensionякий UnWrap Optionalоб'єкт Any.

Коли ви реєструєте об'єкт або роздруковуєте його, ви можете побачити фактичний objectабо <nil>⭕️(поєднання з тексту та візуального символу). Це корисно переглянути, особливо в журналі консолі.

extension Optional {
    var logable: Any {
        switch self {
        case .none:
            return "<nil>|⭕️"
        case let .some(value):
            return value
        }
    }
}

// sample
var x: Int?
print("Logging optional without warning: \(x.logable)")
// → Logging optional without warning: <nil>|⭕️

0

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

extension DefaultStringInterpolation {
  mutating func appendInterpolation<T>(_ optional: T?) {
    appendInterpolation(String(describing: optional))
  }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.