Can anyone explain with one example of warn_unqualified_access
and warn_unused_result
@warn_unused_result
Suppose you have an array representing a deck of cards:
var deck: [Card] = standardDeck.shuffled()
You want to write a function to deal a card to a player. You want to pull the “top” card from the deck, add it to the player's hand, and remove it from the deck:
func dealCard(to player: Player) {
guard let card = deck.last else { fatalError("Ran out of cards") }
player.hand.append(card)
deck.dropLast()
}
When you test your app, you are puzzled. All your players' hands are filled with copies of the same card.
Being new to Swift, you think dropLast
modifies deck
by removing its last element. Sadly, you are mistaken. It returns a new array containing all but the last element of deck
. (Technically it returns an ArraySlice
.)
The compiler and the standard library have conspired to help you figure out the problem. The dropLast
function is annotated with @warn_unused_result
, so Xcode shows you a warning on the dropLast
call:
.../Cards.swift:85:10: Result of call to 'dropLast()' is unused
Seeing the warning, you decide to option-click on dropLast
and read the documentation, which tells you what dropLast
does (returns a new array), and you realize you need to change the line to this:
deck.removeLast()
Many, many functions, in the Swift standard library and in other libraries, are useful mainly for what they return. Ignoring the returned value of one of these functions is usually an error, so Swift makes it easy for the library author to warn the user about this behavior. In fact, Swift will probably soon be modified to apply @warn_unused_result
by default, and to use a new @discardableResult
attribute on the function to suppress the warning.
@warn_unqualified_access
You were so successful with your awesome card game on iOS that you've decided to port it to Mac OS X. On Mac OS X, you use NSView
instead of UIView
to show things on the screen. You're trying to figure out why your custom CardView
is drawing itself incorrectly, so you want to call Swift's standard print
function in drawRect:
class CardView: NSView {
var card: Card
override func drawRect(dirtyRect: NSRect) {
print("Drawing \(card)")
// drawing code here...
}
// rest of CardView here...
}
When you run your app, you're surprised to find that it pops up the print dialog! What's going on? The compiler and NSView
have conspired to help you figure out the problem. The NSView.print
function is annotated with @warn_unqualified_access
, so Xcode shows you a warning on the print
call:
.../CardView.swift:95:9: Use of 'print' treated as a reference to instance method in class 'NSView'
Seeing the warning, you option-click on print
and read the documentation. You learn that NSView
has its own print
method, which lets the user print the contents of the view onto paper. How droll! Now you realize you need to change the call to explicitly use Swift's print
function like this:
Swift.print("Drawing \(card)")
(It is virtually impossible to develop for Mac OS X in Swift without running into this particular case. Repeatedly.)
This sort of problem is much less common than the other problem of ignoring a function's result. NSView.print
is the only case that I can recall running into.
Consider the following example:
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()
This generates two warnings.
One in C.foo()
:
warning: use of 'foo' treated as a reference to instance method in class 'C' use 'self.' to silence this warning
This is because I declared foo
as @warn_unqualified_access
, so it means the compiler wants me to explicitly refer to the object when accessing said member. This is because - for example - calling print
in a subclass of NSView
conflicts between Swift.print
and NSView.print
The second warning is generated in main()
, when calling bar:
warning: result of call to 'bar' is unused c.bar(1)
This is because I am calling bar()
, declared as @warn_unused_result
, and then discarding its result. This is useful, for example, in methods which return you a new value but have no side effects. If you choose to ignore the new value, you essentially wasted work. The compiler can warn you to point that out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With