การใช้การอนุมาน Swift 3 @objc ในโหมด Swift 4 ถูกคัดค้านหรือไม่?


485

สั้น ๆ ในขณะที่ใช้ Xcode 9 Beta ฉันพบว่ามีคำเตือนดังต่อไปนี้:

การใช้การอนุมาน Swift 3 @objc ในโหมด Swift 4 เลิกใช้แล้ว โปรดระบุที่อยู่ที่คำเตือนการอนุมาน @objc ที่เลิกใช้แล้วทดสอบรหัสของคุณด้วยการเปิดใช้งานการบันทึก“ ใช้การอนุมาน Swift 3 @objc” ที่คัดค้านแล้วและปิดใช้งานการอนุมาน Swift 3 @objc **

หลังจากการวิจัยบางอย่างฉันยังไม่รู้ว่าจะแก้ไขปัญหานี้อย่างไร ฉันขอขอบคุณเคล็ดลับอย่างมากเกี่ยวกับวิธีการแก้ไขปัญหานี้รวมถึงคำอธิบายว่าเกิดอะไรขึ้น

เป้าหมายของฉันคือเข้าใจความเข้าใจที่ดีขึ้นว่าเกิดอะไรขึ้นกับรหัสของฉัน


4
ฉันไม่ได้รับจากข้อความเตือนว่าวัตถุเป็นสาเหตุของอะไร Xcode ไม่ได้พูดในบรรทัดที่วัตถุนั้น คำแนะนำใดบ้างที่จะทราบว่าคำเตือนนี้มาจากที่ใด
olyv

คำตอบ:


816

ฉันกำจัดคำเตือนนี้โดยเปลี่ยนการตั้งค่าการสร้าง "Swift 3 @objc" ของเป้าหมายของฉันเป็น "เริ่มต้น"

ปิดใช้การอนุมาน Swift 3 @objc ใน Xcode9

จากบทความนี้ :

ก่อนที่สวิฟท์ 4 คอมไพเลอร์ที่ทำบางประกาศ Swift โดยอัตโนมัติสามารถใช้ได้กับ Objective-C ตัวอย่างเช่นหากหนึ่งคลาสย่อยจาก NSObject คอมไพเลอร์สร้างจุดเข้าใช้งาน Objective-C สำหรับวิธีการทั้งหมดในคลาสดังกล่าว กลไกถูกเรียกว่า @objc อนุมาน

ใน Swift 4 การอนุมาน @objc อัตโนมัติดังกล่าวถูกคัดค้านเนื่องจากมีค่าใช้จ่ายสูงในการสร้างจุดเข้าใช้งาน Objective-C ทั้งหมด เมื่อการตั้งค่า "Swift 3 @objc Inference" ถูกตั้งค่าเป็น "เปิด" จะช่วยให้รหัสเดิมทำงานได้ อย่างไรก็ตามจะแสดงคำเตือนการคัดค้านที่จำเป็นต้องได้รับการแก้ไข ขอแนะนำให้ "แก้ไข" คำเตือนเหล่านี้และเปลี่ยนการตั้งค่าเป็น "เริ่มต้น"ซึ่งเป็นค่าเริ่มต้นสำหรับโครงการ Swift ใหม่

โปรดอ้างอิงข้อเสนอ Swift นี้สำหรับข้อมูลเพิ่มเติม


5
ขอบคุณ Evgenii นี่เป็นวิธีแก้ปัญหาระยะยาวหรือไม่?
DaleK

6
@ DaleK ใช่ฉันเชื่ออย่างนั้น ตามข้อเสนอของ Swift ที่ฉันพูดถึงในคำตอบของฉันการอนุมาน objc นั้นเลิกใช้แล้ว การตั้งค่า "Swift 3 objc Inference" จะปรากฏเฉพาะในโครงการที่ย้ายมาจาก Swift เวอร์ชันเก่า หากมีการสร้างโครงการใหม่การตั้งค่าจะไม่ปรากฏอีกต่อไปซึ่งหมายความว่าการอนุมาน objc ปิดอยู่ ขอแนะนำให้แก้ไขคำเตือนการอนุมานของ objc และตั้งเป็น "ปิด"
Evgenii

4
ข้อความข้อมูลใน XCode แสดงให้เห็นว่า: "การใช้การ@objcอนุมานSwift 3 ในโหมด Swift 4 ถูกคัดค้านโปรดระบุ@objcคำเตือนการอนุมานที่ไม่สนับสนุนการทดสอบรหัสของคุณด้วย@objcการเปิดใช้งานการบันทึก" การใช้การ@objcอนุมานSwift 3 อนุมาน " มีความคิดใดที่จะเปิดใช้งานการ@objcบันทึกการอนุมานSwift 3
courteouselk

4
@courteouselk ตามข้อเสนอ Swift เราสามารถตั้งค่าตัวแปรสภาวะแวดล้อม SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT ให้เป็นค่าตั้งแต่ 1 ถึง 3 เพื่อดูการใช้งานของจุดเข้าใช้งาน Objective-C ในบันทึก
Evgenii

14
เพื่อเพิ่ม - คุณต้องทำสิ่งนี้กับแท็กบิลด์บิลด์ทั้งหมดไม่ใช่แค่โครงการ
Krivvenz

270

- การ@objcอนุมานคืออะไร? เกิดอะไรขึ้น?

ในSwift 3คอมไพเลอร์ infers @objcในหลายสถานที่ดังนั้นคุณไม่จำเป็นต้อง กล่าวอีกนัยหนึ่งมันทำให้แน่ใจว่าจะเพิ่ม@objcให้คุณ!

ในSwift 4คอมไพเลอร์ไม่ทำเช่นนี้ (มาก) ตอนนี้คุณต้องเพิ่ม@objcอย่างชัดเจน

หากคุณมีโครงการ pre-Swift 4 คุณจะได้รับคำเตือนเกี่ยวกับสิ่งนี้ ในโครงการ Swift 4 คุณจะได้รับข้อผิดพลาดในการสร้าง สิ่งนี้ถูกควบคุมผ่านการSWIFT_SWIFT3_OBJC_INFERENCEตั้งค่าการสร้าง ใน 4 โครงการก่อน Swift Onนี้ถูกตั้งค่า ฉันอยากจะแนะนำให้ตั้งค่านี้เป็นDefault(หรือOff) ซึ่งตอนนี้เป็นตัวเลือกเริ่มต้นในโครงการใหม่

ต้องใช้เวลาพอสมควรในการแปลงทุกอย่าง แต่เนื่องจากเป็นค่าเริ่มต้นสำหรับ Swift 4 จึงคุ้มค่าที่จะทำ

- ฉันจะหยุดคำเตือน / ข้อผิดพลาดของคอมไพเลอร์ได้อย่างไร

มีสองวิธีในการแปลงโค้ดของคุณเพื่อให้คอมไพเลอร์ไม่บ่น

หนึ่งคือการใช้งาน@objcในแต่ละฟังก์ชั่นหรือตัวแปรที่จำเป็นต้องสัมผัสกับรันไทม์ Objective-C:

@objc func foo() {

}

อื่น ๆ คือการใช้@objcMembersโดยการClassประกาศ นี้จะทำให้แน่ใจว่าจะเพิ่มโดยอัตโนมัติ@objcไปยังทุกฟังก์ชั่นและตัวแปรในชั้นเรียน นี่เป็นวิธีที่ง่าย แต่มีค่าใช้จ่ายตัวอย่างเช่นมันสามารถเพิ่มขนาดของแอปพลิเคชันของคุณโดยการแสดงฟังก์ชั่นที่ไม่จำเป็นต้องเปิดเผย

@objcMembers class Test {

}

- อะไรคืออะไร@objcและทำไมจึงจำเป็น

หากคุณแนะนำวิธีการหรือตัวแปรใหม่ให้กับคลาส Swift การทำเครื่องหมายพวกเขาเป็นการ@objcเปิดเผยพวกมันไปยังรันไทม์ Objective-C นี้เป็นสิ่งจำเป็นเมื่อคุณมีรหัส Objective-C ที่ใช้ระดับสวิฟท์ของคุณหรือถ้าคุณกำลังใช้ SelectorsObjective-C-ประเภทคุณสมบัติเช่น ตัวอย่างเช่นรูปแบบการดำเนินการเป้าหมาย: button.addTarget(self, action:#selector(didPressButton), for:.touchUpInside)

- ทำไมฉันจะไม่ทำเครื่องหมายทุกอย่าง@objc?

มีเชิงลบที่มาพร้อมกับการทำเครื่องหมายบางอย่างเป็น@objc:

  • แอปพลิเคชันที่เพิ่มขึ้นขนาดไบนารี
  • ไม่มีฟังก์ชั่นโอเวอร์โหลด

โปรดทราบว่านี่เป็นบทสรุประดับสูงมากและมันซับซ้อนกว่าที่ฉันเขียน ฉันขอแนะนำให้อ่านข้อเสนอจริงสำหรับข้อมูลเพิ่มเติม

แหล่งที่มา:


@objcไม่ได้หมายความถึงการจัดส่งแบบไดนามิก Swift มีอิสระในการใช้การจัดส่งแบบคงที่หรือเสมือนจริง (และอาจใช้รหัสที่แตกต่างกันเป็นผล) dynamicคำหลักที่จะต้องบังคับให้สวิฟท์ที่จะใช้การจัดส่งแบบไดนามิก
วิน

7
มีวิธีอื่นในการเพิ่มปุ่มการกระทำหรือไม่ หาก@objcแยกสิ่งที่เราต้องใช้?
Aznix

5
@tefan ใช่อาจจะมีการแปลงเล็กน้อย แยกมันออกเป็นขั้นตอน ออกจากที่SWIFT_SWIFT3_OBJC_INFERENCE Onแปลงเป็น Swift 4 จากนั้นจัดการกับ@objcสิ่งต่าง ๆ หากต้องการทำให้ง่ายขึ้นให้ปฏิบัติตามกฎพื้นฐาน: หากมีการใช้คลาส Swift ในรหัส Objc-C (ผ่านการเชื่อมต่อส่วนหัว) ให้ใช้@objcMembersมิฉะนั้นจะเพิ่มแบบทีละ@objcรายการ เพียงใช้การค้นหา Xcode เพื่อดูว่ามีการเรียกคลาส Swift จาก.mไฟล์ใด ๆหรือไม่ สิ่งนี้จะทำให้การแปลงไม่เจ็บปวด
kgaidis

5
@ DaleK คำตอบนี้ควรได้รับการยอมรับ การยับยั้งการเตือนและทำให้ทุกอย่างทำงานเหมือนที่เคยเป็นใน Swift 3 เป็นตัวเลือก แต่ IMHO ไม่ใช่ตัวเลือกที่ดีที่สุด สิ่งสำคัญคือต้องเข้าใจว่าทำไม@objcการเปลี่ยนแปลงใน Swift 4 จึงตัดสินใจแก้ไขโครงการและทำให้เหมือนเดิม
derpoliuk

2
ขอบคุณสำหรับคำอธิบายสั้น ๆ นี้
Schmoudi

48

ผู้อพยพไม่สามารถระบุฟังก์ชั่นทั้งหมดที่จำเป็น@objc Inferred Objective-C thunks ทำเครื่องหมายว่าเลิกเพื่อช่วยให้คุณพบพวกเขา
•สร้างคำเตือนเกี่ยวกับวิธีการเลิก
•ข้อความคอนโซลเมื่อทำงาน thunks เลิก

ป้อนคำอธิบายรูปภาพที่นี่


1
ดังนั้นฉันควรทำอย่างไรกับ @objc ย้ายมัน? ออกจากมัน? ฉันลบออกไปแล้ว และฉันก็มีคำเตือนเหล่านั้นดังนั้นฉันต้องเพิ่มพวกเขา ในขั้นตอนที่ 3 ฉันควรทำอย่างไรกับสิ่งนั้น
Shial

เพิ่ม @objc ก่อน func
Hassan Taleb

1
ขั้นตอนที่ 3 เกี่ยวกับอะไร คุณสามารถเพิ่มรายละเอียดบาง :)
Shial

และในกรณีของฉันฉันได้รับคำเตือนนี้ แต่ไม่มีรหัสที่ชี้ไป มีสองวิธีที่ทำเครื่องหมาย @objc และดูเหมือนว่ามีเพียงวิธีเดียวที่ต้องการ ฉันเปลี่ยนเป็นค่าเริ่มต้นและยังคงได้รับคำเตือนในระหว่างการคอมไพล์
Maury Markowitz

12

ฉันได้รับคำเตือนนี้ด้วยการตั้งค่า "Swift 3 @objc Inference" = "Default" จากนั้นฉันก็รู้ว่าถูกตั้งค่าไว้สำหรับโครงการ - ไม่ใช่สำหรับเป้าหมาย ดังนั้นตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่า "เริ่มต้น" ในเป้าหมายเพื่อกำจัดคำเตือน


ฉันเสียเวลา 20 นาทีในการค้นหาเพื่อแก้ไขข้อผิดพลาดแม้หลังจากที่ฉันเปลี่ยนเป็นค่าเริ่มต้นในการตั้งค่าโครงการ คุณชี้ให้เห็นอย่างชัดเจนว่ามันจำเป็นต้องเปลี่ยนในเป้าหมายด้วย
SkrewEvery ทุกอย่าง

8

คุณสามารถส่งต่อไปที่ "default" แทน "ON" ดูเหมือนว่าจะยึดมั่นกับตรรกะของ Apple มากขึ้น

(แต่ความคิดเห็นอื่น ๆ ทั้งหมดเกี่ยวกับการใช้@objยังคงใช้ได้)


7

แน่นอนคุณจะกำจัดคำเตือนเหล่านั้นโดยปิดการใช้งาน Swift 3 @objc Inference อย่างไรก็ตามปัญหาที่ลึกซึ้งอาจปรากฏขึ้น ตัวอย่างเช่น KVO จะหยุดทำงาน รหัสนี้ทำงานอย่างสมบูรณ์แบบภายใต้ Swift 3:

for (key, value) in jsonDict {
    if self.value(forKey: key) != nil {
        self.setValue(value, forKey: key)
    }
}

หลังจากที่ย้ายไปสวิฟท์ 4 และการตั้งค่า "สวิฟท์ 3 @objc อนุมาน" เพื่อเริ่มต้น, คุณสมบัติบางอย่างของโครงการของฉันหยุดทำงาน ฉันใช้การแก้ไขข้อบกพร่องและการวิจัยเพื่อค้นหาวิธีแก้ไขปัญหานี้ ตามความรู้ที่ดีที่สุดของฉันนี่คือตัวเลือก:

  • เปิดใช้งาน "Swift 3 @objc Inference" (ใช้ได้เฉพาะเมื่อคุณย้ายข้อมูลโครงการที่มีอยู่จาก Swift 3) ป้อนคำอธิบายรูปภาพที่นี่
  • ทำเครื่องหมายวิธีและคุณสมบัติที่ได้รับผลกระทบเป็น @objc ป้อนคำอธิบายรูปภาพที่นี่
  • เปิดใช้งานการอนุมาน ObjC อีกครั้งสำหรับทั้งคลาสโดยใช้ @objcMembers ป้อนคำอธิบายรูปภาพที่นี่

การเปิดใช้งานการอนุมาน @objc อีกครั้งทำให้คุณมีคำเตือน แต่เป็นวิธีแก้ปัญหาที่เร็วที่สุด โปรดทราบว่ามีให้สำหรับโครงการที่ย้ายข้อมูลจาก Swift เวอร์ชันก่อนหน้าเท่านั้น อีกสองตัวเลือกที่น่าเบื่อมากขึ้นและต้องมีการขุดและทดสอบอย่างละเอียด

ดูเพิ่มเติมที่https://github.com/apple/swift-evolution/blob/master/proposals/0160-objc-inference.md


7

ฉันเป็น iOS dev เป็นครั้งคราว (เร็ว ๆ นี้จะมากขึ้น) แต่ฉันยังไม่พบการตั้งค่าตามคำแนะนำอื่น ๆ (เนื่องจากฉันไม่มีรายการพวงกุญแจที่แสดงคำตอบ) ดังนั้นตอนนี้ฉันก็พบว่าฉันคิดว่า ฉันอาจเพิ่มสแนปชอตนี้ด้วยตำแหน่งที่เน้นซึ่งคุณจะต้องคลิกและค้นหา

  1. เริ่มที่ด้านซ้ายบน
  2. เลือกไอคอนโฟลเดอร์โครงการ
  3. เลือกชื่อโครงการหลักของคุณด้านล่างไอคอนโฟลเดอร์โครงการ
  4. เลือกการตั้งค่าการสร้างทางด้านขวา
  5. เลือกโครงการของคุณภายใต้เป้าหมาย
  6. เลื่อนไปไกลมาก (หรือค้นหาการอนุมานคำในกล่องข้อความค้นหา)

การค้นหาการตั้งค่า


6

คุณสามารถลอง "อัพเดท Pod" และ / หรือ "ทำความสะอาดกระพือ"

ฉันยังตั้งค่านี้เป็น xcode

การตั้งค่าอินเตอร์เฟส Objective-C เป็นดังนี้:

การตั้งค่าอินเตอร์เฟส ObjectiveC


2

Swift 3 @objc Inference การใช้ Swift 3 @objc Inference ในโหมด Swift 4 เลิกใช้แล้ว โปรดระบุคำเตือนการอนุมาน @objc ที่คัดค้านแล้วทดสอบรหัสของคุณด้วยการเปิดใช้งานการบันทึก“ การใช้ Swift 3 @objc inference” ที่คัดค้านแล้วปิดใช้งานการอนุมานด้วยการเปลี่ยนการตั้งค่าการสร้าง "Swift 3 @objc Inference" เป็น "เริ่มต้น" เป้า

ไปที่

  1. ขั้นตอนแรกทำการสร้างการตั้งค่า

  2. ค้นหาในการสร้างการตั้งค่าการอนุมาน

  3. เปลี่ยน swift 3 @objc ค่าเริ่มต้นการอนุมาน

ป้อนคำอธิบายรูปภาพที่นี่


1

สิ่งที่คุณต้องการเพียงแค่ทำการทดสอบรอจนกระทั่งเสร็จสิ้นหลังจากนั้นไปที่การตั้งค่าการสร้างค้นหาในการสร้างการอนุมานการตั้งค่าเปลี่ยน swift 3 @objc Inference เป็น (ค่าเริ่มต้น) นั่นคือทั้งหมดที่ฉันทำและทำงานได้อย่างสมบูรณ์แบบ


0

การใช้การอนุมาน Swift 3 @objc ในโหมด Swift 4 ถูกคัดค้านหรือไม่?

ใช้ func call @objc

func call(){

foo()

}

@objc func foo() {

}

0

ด้านบนของสิ่งที่ @wisekiddo พูดคุณยังสามารถแก้ไขการตั้งค่าการสร้างของคุณในproject.pbxprojไฟล์โดยการตั้งค่า Swift 3 @obj Inference เป็นค่าเริ่มต้นเช่นเดียวSWIFT_SWIFT3_OBJC_INFERENCE = Default;กับการสร้างรสชาติของคุณ (เช่น debug and release) โดยเฉพาะถ้าคุณมาจากสภาพแวดล้อมอื่น นอกเหนือจาก Xcode

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.