Xcode 8/Swift 3: "Выражение типа UIViewController? Is unused" warning

У меня есть следующая функция, которая скомпилирована ранее, но генерирует предупреждение с Xcode 8.

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

"Выражение типа" UIViewController? "не используется".

Почему он говорит это и есть способ его удалить?

Код выполняется, как ожидалось.

Ответ 1

TL; DR

popViewController(animated:) возвращает UIViewController?, и компилятор дает это предупреждение, так как вы не фиксируете значение. Решение состоит в том, чтобы назначить его символу подчеркивания:

_ = navigationController?.popViewController(animated: true)

Swift 3 Изменить

Перед тем, как Swift 3, по умолчанию все методы имели "отбрасываемый результат". Предупреждение не будет происходить, когда вы не поймете, что возвратил метод.

Чтобы сообщить компилятору, что результат должен быть захвачен, вам нужно было добавить @warn_unused_result перед объявлением метода. Он будет использоваться для методов, имеющих изменяемую форму (например, sort и sortInPlace). Вы должны добавить @warn_unused_result(mutable_variant="mutableMethodHere"), чтобы сообщить об этом компилятору.

Однако, с Swift 3, поведение перевернуто. Все методы теперь предупреждают, что возвращаемое значение не будет записано. Если вы хотите сообщить компилятору, что предупреждение не требуется, вы добавляете @discardableResult перед объявлением метода.

Если вы не хотите использовать возвращаемое значение, вам нужно явно указать компилятору, присвоив его знаку подчеркивания:

_ = someMethodThatReturnsSomething()

Мотивация для добавления этого в Swift 3:

  • Предотвращение возможных ошибок (например, с помощью sort, считающих, что он изменяет коллекцию)
  • Явное намерение не захватывать или не собирать результат для других сотрудников

API UIKit оказывается позади, не добавляя @discardableResult для совершенно нормального (если не более общего) использования popViewController(animated:) без записи возвращаемого значения.

Подробнее

Ответ 2

Когда жизнь дает вам лимоны, сделайте расширение:

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 тоже.

Ответ 3

В Swift 3 игнорирование возвращаемого значения функции с объявленным возвращаемым значением приводит к предупреждению.

Один из способов отказаться от этого - отметить функцию атрибутом @discardableResult. Поскольку у вас нет контроля над этой функцией, это не сработает.

Другой способ избавиться от предупреждения - присвоить значение _. Это говорит компилятору, что метод возвращает значение, но вы не хотите его сохранять в памяти.

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

Ответ 4

Снимок экрана 1

Хотя он work correctly if kept as it is, но number of warning increases.

Решение - просто replace it with underscore ( _ ), хотя оно кажется уродливым.

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

Скриншот 2

Ответ 5

Если вы хотите пойти по пути расширений, например, ответ 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)
    }
}

Ответ 6

Другой способ - вы можете развернуть значение self.navigationController? и вызвать функцию popViewController.

    if let navigationController = navigationController {
        navigationController.popViewController(animated: true)
    }