Xcode 8 / Swift 3:“ UIViewController类型的表达吗?未使用”警告


230

我有以下函数,该函数以前已经进行了干净的编译,但是使用Xcode 8会生成警告。

func exitViewController()
{
    navigationController?.popViewController(animated: true)
}

“未使用类型“ UIViewController?的表达式”。

为什么这么说,有没有办法将其删除?

该代码将按预期执行。

Answers:


498

TL; DR

popViewController(animated:)返回UIViewController?,由于您没有捕获该值,编译器会发出警告。解决方案是将其分配给下划线:

_ = navigationController?.popViewController(animated: true)

迅捷3变更

在Swift 3之前,所有方法默认都具有“可丢弃的结果”。当您没有捕获该方法返回的内容时,将不会发生任何警告。

为了告诉编译器应该捕获结果,您必须@warn_unused_result在方法声明之前添加。它将用于具有可变形式(例如sortsortInPlace)的方法。您将添加内容@warn_unused_result(mutable_variant="mutableMethodHere")以告知编译器。

但是,在Swift 3中,行为被翻转了。现在,所有方法都会警告未捕获返回值。如果您想告诉编译器警告是不必要的,请@discardableResult在方法声明之前添加警告。

如果不想使用返回值,则必须通过将其分配给下划线来明确告知编译器:

_ = someMethodThatReturnsSomething()

将其添加到Swift 3的动机:

  • 防止可能的错误(例如,sort认为它会修改集合)
  • 不捕获或需要捕获其他协作者的结果的明确意图

UIKit API似乎落后于此,没有添加@discardableResult完全正常的(如果不是更常见的)用法,popViewController(animated:)而没有捕获返回值。

阅读更多


15
(在我看来)这绝对是Swift 2的一大步,特别是当存在这样的方法时,即使它们确实返回了一个值,也有完全有效的用例,而您只是不使用它。
Nicolas Miari

15
1.您不需要let::您只需将_赋给_而无需在其之前加上letvar
rickster

1
@rickster不知道会补充答案。
tktsubota

5
2. @NicolasMiari提交错误@discardableResult对于确实返回值的函数,有一个注释(),但可以预期该函数可能会忽略该返回值。UIKit只是没有将该注释应用于其API。
rickster

37
这是可怕的语法。他们为什么要这样做?uck
David S.

38

当生活给你柠檬时,请扩展一下:

import UIKit

extension UINavigationController {
    func pop(animated: Bool) {
        _ = self.popViewController(animated: animated)
    }

    func popToRoot(animated: Bool) {
        _ = self.popToRootViewController(animated: animated)
    }
}

请注意,添加类似内容@discardableResult func pop(animated: Bool) -> UIViewController?将导致您尝试避免相同的警告。

使用扩展名,您现在可以编写:

func exitViewController()
{
    navigationController?.pop(animated: true)
}

func popToTheRootOfNav() {
    navigationController?.popToRoot(animated: true)
}

编辑:也添加了popToRoot。


这应该是公认的解决方案,因为它是对Xcode更新中肯定要修复的最干净的修复。
菲利普·百老汇

24

在Swift 3中,忽略具有已声明返回值的函数的返回值将导致警告。

退出此功能的一种方法是使用@discardableResult属性标记功能。由于您无法控制此功能,因此无法使用。

摆脱警告的另一种方法是将值分配给_。这告诉编译器您知道该方法返回一个值,但是您不想将其保留在内存中。

let _ = navigationController?.popViewController(animated: true)

2
我猜我们将不得不坚持丑陋,_直到Apple使用此新属性更新UIKit。
Nicolas Miari

2
不幸的是,@discardableResult它不起作用(至少它仍然对8b4嘶哑)。弗里德里希·席勒(Friedrich Schiller)喜欢烂苹果。大概是口味问题:-(
qwerty_so

5

屏幕截图1

虽然它work correctly if kept as it is但是number of warning increases.

解决方案是,replace it with underscore ( _ )尽管看起来很丑陋。

Eg.  _ = navigationController?.popViewController(animated: true)

屏幕截图2


2

在这种情况下使用disableableResult

根据<Swift编程语言>中的语言参考-属性一章。

rejectableResult

将此属性应用于函数或方法声明,以在调用返回值的函数或方法而不使用其结果时抑制编译器警告。

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Attributes.html#//apple_ref/doc/uid/TP40014097-CH35-ID347

在<Swift编程语言>的语言指南-方法一章中还有一个演示。

@discardableResult
    mutating func advance(to level: Int) -> Bool {
    ...
return true
}

因为调用先进方法(to :)忽略返回值不一定是错误的代码,所以此函数标有@discardableResult属性。有关此属性的更多信息,请参见属性。

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Methods.html#//apple_ref/doc/uid/TP40014097-CH15-ID234


0

如果您想走CodeReaper的答案之类的扩展之路,则应使用@descardableResult。这样可以保留所有可能性,但不会发出警告。

import UIKit

extension UINavigationController {
    @discardableResult func pop(animated: Bool) -> UIViewController? {
        return self.popViewController(animated: animated)
    }

    @discardableResult func popToRoot(animated: Bool) -> [UIViewController]? {
        return self.popToRootViewController(animated: animated)
    }
}

-1

另一种方法是您可以解开self.navigationController?值并调用popViewController函数。

    if let navigationController = navigationController {
        navigationController.popViewController(animated: true)
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.