Xcode 8 / Swift 3: “UIViewController türünün ifadesi? kullanılmıyor ”uyarısı


230

Daha önce temiz bir şekilde derlenmiş ancak Xcode 8 ile bir uyarı üreten aşağıdaki fonksiyona sahibim.

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

Msgstr "" UIViewController? "Türündeki ifade kullanılmıyor".

Neden bunu söylüyor ve kaldırmanın bir yolu var mı?

Kod beklendiği gibi yürütülür.

Yanıtlar:


498

TL; DR

popViewController(animated:)döndürür UIViewController?ve derleyici değeri yakalamadığınız için bu uyarıyı verir. Çözüm, bunu bir alt çizgiye atamaktır:

_ = navigationController?.popViewController(animated: true)

Swift 3 Değişikliği

Swift 3'ten önce, tüm yöntemlerin varsayılan olarak "çıkarılabilir bir sonucu" vardı. Yöntemin döndürdüğünü yakalamadığınızda uyarı oluşmaz.

Derleyiciye sonucun yakalanması gerektiğini söylemek için @warn_unused_result, yöntem bildiriminden önce eklemeniz gerekiyordu . Değişken bir forma (örn. sortVe sortInPlace) sahip yöntemler için kullanılır . @warn_unused_result(mutable_variant="mutableMethodHere")Derleyiciye anlatmak için eklersiniz .

Ancak, Swift 3 ile davranış ters çevrilir. Tüm yöntemler artık dönüş değerinin yakalanmadığı konusunda uyarıyor. Derleyiciye uyarının gerekli olmadığını söylemek istiyorsanız @discardableResult, yöntem bildiriminden önce ekleyin .

Dönüş değerini kullanmak istemiyorsanız , derleyiciye bir alt çizgiye atayarak bunu açıkça belirtmeniz gerekir:

_ = someMethodThatReturnsSomething()

Swift 3'e eklemek için motivasyon:

  • Olası hataların önlenmesi (örn. sort koleksiyonu değiştirdiğini düşünerek)
  • Diğer ortak çalışanlar için net bir şekilde yakalama veya sonucu yakalama gereği

UIKit API'sinin bunun arkasında olduğu görülüyor , dönüş değerini yakalamadan @discardableResulttamamen normal (daha yaygın değilse) kullanım için eklenmiyor popViewController(animated:).

Daha fazla oku


15
Bu da olsa o, böyle yöntemler vardır, özellikle, kesinlikle (Bence) Swift 2 bir adım geri yapmak bir değer döndürmez, şunu kullanmayın tamamen geçerli kullanım örnekleri bulunmaktadır.
— Nicolas Miari

15
1. Şunlara ihtiyacınız yoktur let: _ ile önce letveya olmadan atayabilirsiniz var.
— rickster

1
@rickster Bunun cevaba ekleyeceğini bilmiyordum.
— tktsubota

5
2. @NicolasMiari Hata gönderin . @discardableResultDeğer döndüren ancak dönüş değerini göz ardı etmesinin beklendiği işlevler için bir ek açıklama ( ) vardır . UIKit bu ek açıklamayı API'larına uygulamadı.
— rickster

37
Bu korkunç bir sözdizimidir. Neden bunu yapsınlar? Yuck.
— David

38

Hayat sana limon verdiğinde, bir uzantı yap:

import UIKit

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

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

Not gibi belirtti şey@discardableResult func pop(animated: Bool) -> UIViewController? , kaçınmaya çalıştığınız uyarı ile sonuçlanacağını .

Uzantı ile artık yazabilirsiniz:

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

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

Düzenleme: popToRoot da eklendi.


Bu, kabul edilen çözüm olmalıdır, çünkü bir Xcode güncellemesinde düzeltilecekleri kesin olarak belirleyen en temiz çözümdür.
— Philip Broadway

24

Swift 3'te, beyan edilen dönüş değeri olan bir işlevin dönüş değerini dikkate almamak bir uyarı ile sonuçlanır.

Bunu devre dışı bırakmanın bir yolu, işlevi @discardableResultöznitelikle işaretlemektir . Bu işlev üzerinde kontrol sahibi olmadığınız için, bu işe yaramaz.

Uyarıdan kurtulmanın diğer yöntemi değeri atamaktır _. Bu derleyiciye yöntemin bir değer döndürdüğünü bildiğinizi, ancak bunu bellekte tutmak istemediğinizi söyler.

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

2
Sanırım _Apple bu yeni özellik ile UIKit'i güncelleyene kadar çirkin kalmamız gerekecek.
— Nicolas Miari

2
Ne yazık ki @discardableResultçalışmıyor (en azından hala 8b4 ile dolanıyor). Friedrich Schiller çürük elmaları severdi. Muhtemelen bir tat meselesi :-(
— qwerty_so

5

Ekran görüntüsü 1

Rağmen work correctly if kept as it isamanumber of warning increases.

Çözüm, replace it with underscore ( _ )çirkin gözükmesine rağmen.

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

Ekran görüntüsü 2


2

Bu durumda discardableResult öğesini kullanın .

<Swift Programming Language> (Dil Programlama Dili) bölümüne göre Dil Referansı - Özellikler.

discardableResult

Bir değeri döndüren işlev veya yöntem sonucunu kullanmadan çağrıldığında derleyici uyarısını bastırmak için bu özniteliği bir işlev veya yöntem bildirimine uygulayın.

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

Ayrıca <Hızlı Programlama Dili> bölümünde Dil Kılavuzu - Yöntemler bölümünde bir demo bulunmaktadır.

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

Dönüş değerini yok saymak için advance (to :) yöntemini çağıran kod için bir hata olması gerekmediğinden, bu işlev @discardableResult özniteliğiyle işaretlenir. Bu özellik hakkında daha fazla bilgi için bkz. Özellikler.

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


0

CodeReaper'ın yanıtı gibi uzantıların yoluna gitmek istiyorsanız kullanmalısınız @descardableResult. Bu, tüm olasılıkları korur, ancak uyarıyı susturur.

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

Başka bir yol, self.navigationController?değeri açıp popViewControllerişlevi çağırabilmenizdir .

    if let navigationController = navigationController {
        navigationController.popViewController(animated: true)
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.