Ошибка при распаковке

Я создал новый оператор, который привязывает значение к цели, только если значение не равно нулю, в противном случае ничего не делает. В основном это синтетический сахар, if let foo = foo { faa = foo } :

 infix operator =? {} func =?<T>(inout lhs: T, rhs: T?) { if let rhs = rhs { lhs = rhs } } func =?<T>(inout lhs: T?, rhs: T?) { if let rhs = rhs { lhs = rhs } } 

Таким образом, я могу сохранить некоторые типизации:

 // instead this: if let x = maybeX { z = x } // I can do this: z =? x 

Моя проблема в том, что когда я добираюсь до строки выполнения ( z =? x ), я сбой даже перед входом в реализацию func с исключением:

 fatal error: unexpectedly found nil while unwrapping an Optional value 

Кажется, Swift пытается заставить распаковать x даже когда реализация принимает T? ,

Есть идеи?

2 Solutions collect form web for “Ошибка при распаковке”

Это оказалось моей ошибкой … Я использовал foo.z = ... где foo был nil UIImageView! … дамм просмотров от nib …

Я бы с радостью изменил свою реализацию с помощью оператора nil coalescing после предложения @RMenke, но насколько я знаю, это приведет к избыточному действию установки z в z, когда x равно nil … например:

 var z = someFoo() var x: Int? = nil z = x ?? z // will this re-write z's reference to z again or simply do nothing? 

@MartinR сделал важный комментарий:

если оператор (или функция) принимает inout-параметр, тогда свойство setter будет вызываться при возврате, даже если вы не назначаете новое значение внутри оператора

Пытаясь решить проблему, я сделал следующее расширение как более чистую версию подхода _ = foo.map... :

 extension Optional { public func use<U>(@noescape f: (Wrapped) throws -> U) rethrows { _ = try self.map(f) } } //then: x.use{ z = $0 } 

Вероятно, это лучше, так как он не вызывает z setter, когда x равен нулю, но является ли это самым чистым / ясным способом?

Ваш оператор работает, но вы должны были использовать целые опции: foo? .z = …

Однако это даст вам еще один вид ошибки, когда foo – это nil, который вы можете исправить, добавив

 func =?<T>(lhs: T??, rhs: T?) -> () {} 

Эта версия «ничего не делает» оператора поглощает неизменяемую версию параметра, которую вы получаете при передаче необязательной цепочки с нулем перед последним членом.

  • base64EncodedStringWithOptions в Swift не работает с ошибкой компиляции
  • Загрузка ресурса (например, раскадровки) в структуре Swift
  • Swift Как отправлять различные уведомления через 2 недели
  • Изменить значения, не влияя на сохраненные объекты - Realm swift
  • Строка не конвертируется в NSMutableString
  • Предупреждение компилятора в бета-версии XCode6 - «Сокращенные имена внешних параметров»
  • Firebase iOS Вход в Google - использование незаявленного типа GIDSignInDelegate
  • Я получил исключение из dateFormatter с помощью «EEE MMM dd HH: mm: ss z yyyy»
  • Приложения на основе Swift работают на OS X 10.9 / iOS 7 и ниже?
  • В чем разница setScale и размера SKSpriteNodes в SpriteKit и Swift?
  • dyld: библиотека не загружена: @executable_path /../ Frameworks /
  • Скрыть курсор в UITextView - Swift
  • Interesting Posts
    PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.