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

Я создал новый оператор, который привязывает значение к цели, только если значение не равно нулю, в противном случае ничего не делает. В основном это синтетический сахар, 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? ,

Есть идеи?

Это оказалось моей ошибкой … Я использовал 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?) -> () {} 

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

  • Swift - как использовать malloc?
  • Swift UIApplication.setStatusBarStyle Не работает
  • PrefetchRowsAt не будет работать, если не осталось строк
  • SWIFT: что означает ошибка «Thread 1: EXC_BAD_INSTRUCTION (код = EXC_I386_INVOP, subcode = 0x0)» означает?
  • Тип переменной огня Аламофир не имеет членов индекса
  • Получить историю чата XMPP OpenFire
  • Интерактивное уведомление, не показывающее кнопки ios 9.2
  • изменить шрифт метки без изменения размера
  • Элемент навигации IOS 11 с включенным взаимодействием с пользователем не работает
  • Ошибка приложения, «Потерянное соединение»
  • Как добавить интерфейс навигации после создания контроллера панели вкладок программным способом (Swift)
  • Давайте будем гением компьютера.