@warn_unqualified_access和@warn_unused_result之间的区别?

Pad*_*gam 9 swift

任何人都可以用一个例子来解释 warn_unqualified_accesswarn_unused_result

rob*_*off 34

@warn_unused_result

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

var deck: [Card] = standardDeck.shuffled()
Run Code Online (Sandbox Code Playgroud)

你想写一个功能来向玩家发牌.你想从牌组中拉出"顶级"牌,将其添加到玩家手中,然后将其从牌组中移除:

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

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

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

编译器和标准库密谋帮助您找出问题所在.该dropLast函数带有注释@warn_unused_result,因此Xcode会在dropLast调用时向您显示警告:

.../Cards.swift:85:10: Result of call to 'dropLast()' is unused
Run Code Online (Sandbox Code Playgroud)

看到警告,您决定选择 - 单击dropLast并阅读文档,它会告诉您dropLast(返回一个新数组)的内容,并且您意识到需要将行更改为:

    deck.removeLast()
Run Code Online (Sandbox Code Playgroud)

Swift标准库和其他库中的许多函数主要用于返回它们.忽略其中一个函数的返回值通常是一个错误,因此Swift使库作者可以轻松地警告用户此行为.事实上,Swift可能很快会被修改@warn_unused_result默认应用,并@discardableResult在函数上使用新属性来抑制警告.

@warn_unqualified_access

你在iOS上的精彩纸牌游戏中取得了如此成功,你决定将它移植到Mac OS X.在Mac OS X上,你使用NSView而不是UIView在屏幕上显示东西.你试图找出你的自定义为什么CardView不正确地绘制自己,所以你想要调用Swift的标准print函数drawRect:

class CardView: NSView {

    var card: Card

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

        // drawing code here...
    }

    // rest of CardView here...
}
Run Code Online (Sandbox Code Playgroud)

当您运行应用程序时,您会惊讶地发现它会弹出打印对话框!这是怎么回事?编译器和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'
Run Code Online (Sandbox Code Playgroud)

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

        Swift.print("Drawing \(card)")
Run Code Online (Sandbox Code Playgroud)

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

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

  • 很好的解释!使用这些属性背后的原因与它们的效果同样重要.:-) (2认同)

Enr*_*ata 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()
Run Code Online (Sandbox Code Playgroud)

这会产生两个警告.

一个在C.foo():

警告:使用'foo'作为对'C'类中实例方法的引用,使用'self'.沉默这个警告

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

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

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

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