Xcode 8 / Swift 3:“ การแสดงออกของประเภท UIViewController? ไม่มีการเตือน”


230

ฉันมีฟังก์ชั่นต่อไปนี้ซึ่งเรียบเรียงอย่างเรียบร้อยก่อนหน้านี้ แต่สร้างคำเตือนด้วย Xcode 8

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

"นิพจน์ประเภท" UIViewController? "ไม่ได้ใช้"

เหตุใดจึงพูดอย่างนี้และมีวิธีลบออกหรือไม่

รหัสดำเนินการตามที่คาดไว้

คำตอบ:


498

TL; DR

popViewController(animated:)ผลตอบแทนUIViewController?และคอมไพเลอร์ให้คำเตือนนั้นเพราะคุณไม่ได้เก็บค่า ทางออกคือการกำหนดให้ขีดล่าง:

_ = navigationController?.popViewController(animated: true)

Swift 3 Change

ก่อนที่ Swift 3 วิธีการทั้งหมดจะมี "ผลลัพธ์ที่ถูกทิ้ง" โดยค่าเริ่มต้น ไม่มีคำเตือนเกิดขึ้นเมื่อคุณไม่ได้จับภาพสิ่งที่วิธีการกลับมา

เพื่อบอกคอมไพเลอร์ว่าควรจับผลลัพธ์คุณต้องเพิ่ม@warn_unused_resultก่อนการประกาศเมธอด มันจะใช้สำหรับวิธีการที่มีรูปแบบที่ไม่แน่นอน (เช่นsortและsortInPlace) คุณจะเพิ่ม@warn_unused_result(mutable_variant="mutableMethodHere")เพื่อบอกคอมไพเลอร์ของมัน

อย่างไรก็ตามด้วย Swift 3 พฤติกรรมจะถูกพลิก วิธีการทั้งหมดในขณะนี้เตือนว่าค่าตอบแทนจะไม่ถูกจับ ถ้าคุณต้องการบอกคอมไพเลอร์ว่าไม่จำเป็นต้องเตือนคุณเพิ่ม@discardableResultก่อนการประกาศวิธีการ

หากคุณไม่ต้องการใช้ค่าส่งคืนคุณต้องบอกคอมไพเลอร์อย่างชัดเจนด้วยการกำหนดให้ขีดล่าง:

_ = someMethodThatReturnsSomething()

แรงจูงใจในการเพิ่มสิ่งนี้ลงใน Swift 3:

  • การป้องกันข้อผิดพลาดที่อาจเกิดขึ้น (เช่นการใช้sortความคิดจะปรับเปลี่ยนการรวบรวม)
  • ความตั้งใจอย่างชัดแจ้งที่จะไม่จับภาพหรือต้องการจับผลลัพธ์สำหรับผู้ทำงานร่วมกันคนอื่น ๆ

UIKit API ดูเหมือนว่าจะไม่สามารถเพิ่มการ@discardableResultใช้งานปกติได้อย่างสมบูรณ์แบบ (หากไม่ใช่เรื่องธรรมดา) popViewController(animated:)โดยไม่ต้องจับค่าส่งคืน

อ่านเพิ่มเติม


15
นี่คือ (ในความคิดของฉัน) เป็นขั้นตอนกลับจาก Swift 2 โดยเฉพาะอย่างยิ่งเมื่อมีวิธีการเช่นนี้แม้ว่าพวกเขาจะคืนค่ามีกรณีการใช้ที่ถูกต้องสมบูรณ์แบบที่คุณไม่ได้ใช้
นิโคลัส Miari

15
1. คุณไม่จำเป็นต้องlet: คุณสามารถเพียงแค่กำหนดจะ _ โดยไม่ก่อนหน้านั้นด้วยหรือlet var
rickster

1
@ เคล็ดลับไม่ทราบว่าจะเพิ่มคำตอบ
tktsubota

5
2. @NicolasMiari ไฟล์ข้อผิดพลาด มีคำอธิบายประกอบ ( @discardableResult) สำหรับฟังก์ชั่นที่ส่งคืนค่า แต่ในกรณีที่คาดว่าจะมีคนส่งคืนค่า UIKit ไม่ได้ใช้คำอธิบายประกอบนั้นกับ API ของพวกเขา
rickster

37
นี่เป็นไวยากรณ์ที่น่ากลัว ทำไมพวกเขาถึงทำเช่นนี้? yuck
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
Philip Broadway

24

ใน Swift 3 การละเว้นค่าส่งคืนของฟังก์ชันที่มีค่าส่งคืนที่ประกาศไว้จะทำให้เกิดคำเตือน

วิธีหนึ่งในการเลือกไม่ใช้สิ่งนี้คือทำเครื่องหมายฟังก์ชันด้วย@discardableResultแอตทริบิวต์ เนื่องจากคุณไม่สามารถควบคุมฟังก์ชันนี้ได้จึงไม่ทำงาน

วิธีการอื่น ๆ _ในการกำจัดของคำเตือนคือการกำหนดค่า นี่เป็นการบอกคอมไพเลอร์ที่คุณรู้ว่าวิธีคืนค่า แต่คุณไม่ต้องการเก็บไว้ในหน่วยความจำ

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

2
ฉันเดาว่าเราจะต้องติดกับอัปลักษณ์_จนกว่า Apple จะอัปเดต UIKit ด้วยคุณลักษณะใหม่นี้
นิโคลัส 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

ใช้discardableResultในเงื่อนไขนี้

ตาม <Swift Programming Language> บทที่การอ้างอิงภาษา - คุณสมบัติ

discardableResult

ใช้แอ็ตทริบิวต์นี้กับการประกาศฟังก์ชันหรือเมธอดเพื่อยับยั้งการเตือนคอมไพเลอร์เมื่อฟังก์ชันหรือเมธอดที่ส่งคืนค่าถูกเรียกโดยไม่ใช้ผลลัพธ์

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
}

เนื่องจากไม่จำเป็นต้องมีข้อผิดพลาดสำหรับรหัสที่เรียกวิธีการล่วงหน้า (ถึง :) เพื่อละเว้นค่าส่งคืนฟังก์ชันนี้จึงถูกทำเครื่องหมายด้วยแอตทริบิวต์ @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)
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.