@warn_unqualified_access和@warn_unused_result之间的区别?

时间:2016-02-18 03:50:12

标签: swift

任何人都可以使用warn_unqualified_accesswarn_unused_result

的一个示例进行解释

2 个答案:

答案 0 :(得分:31)

@warn_unused_result

假设你有一个代表一副牌的数组:

var deck: [Card] = standardDeck.shuffled()

你想写一个功能来将牌交给玩家。你想从牌组中拉出“顶级”牌,将其添加到玩家手中,然后将其从牌组中移除:

func dealCard(to player: Player) {
    guard let card = deck.last else { fatalError("Ran out of cards") }
    player.hand.append(card)
    deck.dropLast()
}

当您测试应用时,您会感到困惑。所有玩家的手上都装满了同一张牌的副本。

作为Swift的新手,您认为dropLast通过删除其最后一个元素来修改deck。可悲的是,你错了。它返回一个 new 数组,其中包含deck的最后一个元素。 (从技术上讲,它返回ArraySlice。)

编译器和标准库密谋帮助您找出问题所在。 dropLast功能使用@warn_unused_result进行了注释,因此Xcode会在dropLast来电时向您显示警告:

.../Cards.swift:85:10: Result of call to 'dropLast()' is unused

看到警告,您决定按住dropLast选项并阅读文档,该文档告诉您dropLast做了什么(返回一个新数组),并且您意识到需要更改该行对此:

    deck.removeLast()

Swift标准库和其他库中的许多函数主要用于返回它们。忽略其中一个函数的返回值通常是一个错误,因此Swift使库作者可以轻松地警告用户此行为。实际上,Swift will probably soon be modified默认情况下应用@warn_unused_result,并在函数上使用新的@discardableResult属性来抑制警告。

@warn_unqualified_access

你在iOS上的精彩纸牌游戏非常成功,你决定将它移植到Mac OS X.在Mac OS X上,你使用NSView而不是UIView来显示屏幕。您试图找出自定义CardView错误的原因,因此您想在print

中调用Swift的标准drawRect:函数
class CardView: NSView {

    var card: Card

    override func drawRect(dirtyRect: NSRect) {
        print("Drawing \(card)")

        // drawing code here...
    }

    // rest of CardView here...
}

当您运行应用程序时,您会惊讶地发现它会弹出打印对话框!这是怎么回事?编译器和NSView密谋帮助您找出问题所在。 NSView.print功能使用@warn_unqualified_access进行了注释,因此Xcode会在print来电时向您显示警告:

.../CardView.swift:95:9: Use of 'print' treated as a reference to instance method in class 'NSView'

看到警告,您可以选择print并阅读文档。您了解到NSView有自己的print方法,该方法允许用户将视图内容打印到纸上。怎么可笑!现在您意识到需要更改调用以显式使用Swift的print函数,如下所示:

        Swift.print("Drawing \(card)")

(在没有遇到这种特殊情况的情况下,几乎不可能在Swift中为Mac OS X开发。反复。)

这种问题比忽略函数结果的其他问题要少得多。 NSView.print是唯一一个我记得碰到的案例。

答案 1 :(得分:5)

考虑以下示例:

class C { 
   @warn_unqualified_access func foo(x: Int) -> Int { return x } 
   @warn_unused_result func bar(x: Int) -> Int { return foo(x) } 
 } 

func main() {
  let c = C()
  c.foo(1)
  c.bar(1)
}

main()

这会产生两个警告。

C.foo()中的一个:

  

警告:使用'foo'作为对'C'类中实例方法的引用            使用'自我'。沉默这个警告

这是因为我声明了foo as @warn_unqualified_access,所以这意味着编译器希望我在访问所述成员时显式引用该对象。这是因为 - 例如 - 在printNSView之间的Swift.print子类中调用NSView.print

调用bar时,main()会生成第二个警告:

  

警告:调用'bar'的结果未使用c.bar(1)

这是因为我正在调用bar(),声明为@warn_unused_result,然后丢弃其结果。例如,在返回新值但没有副作用的方法中,这很有用。如果您选择忽略新值,则基本上浪费了工作。编译器可以警告你指出这一点。