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.