【问题标题】:Value of optional type 'NSNumber' not unwrapped; did you mean to use '!' or '?'?可选类型“NSNumber”的值未解包;你的意思是用'!'或者 '?'?
【发布时间】:2014-06-14 21:07:16
【问题描述】:

在我的 UIFontExtension.swift 文件中,我收到一个 Swift 编译器错误,指出...

Value of optional type 'NSNumber' not unwrapped; did you mean to use '!' or '?'?

这个错误指向 w!h! 在我最后有 cmets 的行上。

import Foundation
import UIKit

extension UIFont {
  func sizeOfString (string: String, maxWidth w: CGFloat?, maxHeight h: CGFloat?) -> CGSize {
    var width = w != nil ? w! : DBL_MAX // Error on this line
    var height = h != nil ? h! : DBL_MAX // And on this line
    var size = CGSize(width: width, height: height)
    var options = NSStringDrawingOptions.UsesLineFragmentOrigin
    var attributes = [NSFontAttributeName: self]
    var nsstring = NSString(string: string)
    return nsstring.boundingRectWithSize(size, options: options, attributes: attributes, context: nil).size
  }
}

这只是一个错误吗?

【问题讨论】:

  • 我的 Swift REPL 不会产生您所描述的错误。
  • 有趣。如果您不使用本地别名(在函数中使用 maxWidth 和 maxHeight 而不是 w 和 h),是否仍然会发生这种情况?

标签: swift


【解决方案1】:

哦,等等,我认为问题(也许)是分配被解释为比比较具有更高的优先级。编译器不知道比较应该是针对整个赋值还是只针对赋值的表达式。尝试添加括号:

extension UIFont {
  func sizeOfString (string: String, maxWidth w: CGFloat?, maxHeight h: CGFloat?) -> CGSize {
    var width = (w != nil ? w! : DBL_MAX) // Error on this line
    var height = (h != nil ? h! : DBL_MAX) // And on this line
    var size = CGSize(width: width, height: height)
    var options = NSStringDrawingOptions.UsesLineFragmentOrigin
    var attributes = [NSFontAttributeName: self]
    var nsstring = NSString(string: string)
    return nsstring.boundingRectWithSize(size, options: options, attributes: attributes, context: nil).size
  }
}

我认为没有括号,分配被解释为:

    (var width = w) != nil ? w! : DBL_MAX // Error on this line

【讨论】:

  • 太棒了!你是对的。这是最简单的解决方案。
  • @aleclarson:我认为这仍然是一个错误,因为如果它是真的编译器应该将类型推断为GFloat? 而不是GFloat
  • @aleclarson:也就是说width的类型应该被推断为GFloat?。看起来他们使用不同的代码来推断类型而不是确定优先级,这样做说明了为什么这是一个坏主意。
  • 这没有意义。与 c 语言家族不同,赋值不是 swift 中的表达式,因此在赋值之前应始终对右侧进行完全评估。我似乎记得一些关于将可选数字作为 NSNumbers 传递给目标 c 类的讨论。您收到的错误消息更符合您的要求。
  • @David:“这没有意义。与 c 语言家族不同,赋值不是 swift 中的表达式,因此在赋值之前应始终对右侧进行全面评估。”是的,这就是为什么它是错误的。阅读我上面的cmets。您可以将功能移出扩展程序并且工作正常的事实似乎证明了这一点。至于NSNumberCGFloat 是 Fl​​oat 或 Double 的 typedef(相当于 Swift 的 Int)。 FloatDouble 扩展 NSNumber。因此可以合理地假设专门处理CGFloats 的代码将它们视为NSNumber
【解决方案2】:

通过改变这三行来解决它...

func sizeOfString (string: String, maxWidth w: CGFloat?, maxHeight h: CGFloat?) -> CGSize {
  var width = w != nil ? w! : DBL_MAX // Error on this line
  var height = h != nil ? h! : DBL_MAX // And on this line

...到这个...

func sizeOfString (string: String, maxWidth w: CGFloat, maxHeight h: CGFloat) -> CGSize {
  var width = w < 0 ? CGFLOAT_MAX : w
  var height = h < 0 ? CGFLOAT_MAX : h

CGFloat 参数不再是可选的。相反,当我不需要限制宽度和/或高度时,我会将负值转换为 CGFLOAT_MAX

【讨论】:

    【解决方案3】:

    这是绕过此错误的另一种方法...

    var width: CGFloat
    if w {
      width = w!
    } else {
      width = CGFLOAT_MAX
    }
    
    var height: CGFloat
    if h {
      height = h!
    } else {
      height = CGFLOAT_MAX
    }
    

    显然,与可选项相结合的三元运算符导致了问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-12
      • 2015-11-11
      • 2018-10-09
      相关资源
      最近更新 更多