วิธีกำหนดให้โปรโตคอลสามารถนำมาใช้โดยคลาสเฉพาะเท่านั้น


92

ฉันต้องการโปรโตคอลนี้:

protocol AddsMoreCommands {
     /* ... */
}

จะนำมาใช้โดยคลาสที่สืบทอดจากคลาสUIViewControllerเท่านั้น หน้านี้บอกฉันว่าฉันสามารถระบุได้ว่ามันถูกนำมาใช้โดยคลาสเท่านั้น (เมื่อเทียบกับโครงสร้าง) โดยการเขียน

protocol AddsMoreCommands: class {
}

แต่ฉันไม่เห็นวิธีการกำหนดว่าจะต้องใช้เฉพาะคลาสใดคลาสหนึ่งเท่านั้น หน้านั้นพูดถึงการเพิ่มwhereส่วนขยายของโปรโตคอลในภายหลังเพื่อตรวจสอบความสอดคล้อง แต่ฉันไม่สามารถดูวิธีปรับเปลี่ยนได้

extension AddsMoreCommands where /* what */ {
}

มีวิธีทำไหม? ขอบคุณ!

คำตอบ:


115
protocol AddsMoreCommands: class {
    // Code
}

extension AddsMoreCommands where Self: UIViewController {
    // Code
}

4
ฉันเกือบจะมีแล้ว ... ฉันเขียนselfแทนSelf:-( ขอบคุณมากที่ใช้งานได้ดี!
emrys57

สำหรับฉันสิ่งนี้ทำให้เกิดความแปลกทางวากยสัมพันธ์เมื่อฉันใช้สิ่งนี้ร่วมกับการแคสต์
Chris Prince

3
วิธีนี้จะใช้ไม่ได้หากคุณต้องการรวมคุณสมบัติในโปรโตคอลเนื่องจากส่วนขยายไม่สามารถมีคุณสมบัติที่จัดเก็บไว้ได้
ชิม

1
สามารถจัดเก็บได้อย่างถูกต้องคุณต้องใช้สิ่งนี้: objc_getAssociatedObject (self & KeyName) เป็น? PropertyType
Michał Ziobro

นอกจากนี้ยังต้องมีการแคสต์เมื่อการประกาศ let / var มีประเภทAddsMoreCommandsแต่วิธีการที่คุณส่งไปคาดว่า aUIViewController
GoatInTheMachine

81

สิ่งนี้สามารถทำได้โดยไม่ต้องขยาย:

protocol AddsMoreCommands: UIViewController {
    // code
}

ซึ่งเหมือนกับ:

protocol AddsMoreCommands where Self: UIViewController {
   // code
}

ฉันมักจะใช้ตัวเลือกแรก IIRC ฉันอ่านเมื่อสักครู่ที่ผ่านมาในเอกสาร Swift ซึ่งเป็นวิธีที่แนะนำเมื่อข้อ จำกัด คือSelfถ้าเป็นข้อ จำกัด อื่น ๆ เช่นประเภทการเชื่อมโยงคือเมื่อwhereสามารถใช้ได้

โปรดสังเกตว่าเนื่องจากUIViewControllerเป็นclassเช่นกันโปรโตคอลนี้สามารถนำไปใช้กับคุณสมบัติที่อ่อนแอเช่นผู้รับมอบสิทธิ์

แก้ไข 2021/01/05 : โซลูชันที่โพสต์ก่อนหน้านี้มีคำเตือนฉันได้ลบออกและใช้อันนี้ซึ่งไม่มีคำเตือนใด ๆ


5
มันบังเอิญแค่ไหนที่ฉันคลิกคำถามอายุสองขวบและหาคำตอบที่สมบูรณ์แบบโพสต์เมื่อหนึ่งชั่วโมงที่แล้ว😲
Oscar Apeland

Xcode 9.1 กำลังเตือนฉันเกี่ยวกับคำพูดนี้: ข้อ จำกัด ของเค้าโครงซ้ำซ้อน 'Self': 'AnyObject' ข้อ จำกัด ของเค้าโครง 'ตนเอง': 'AnyObject' มีนัยที่นี่ การเปลี่ยนรหัสของฉันเป็นรูปแบบของคำตอบที่ยอมรับดูเหมือนจะดีกว่า
Zig

2
จากโปรโตคอลคลาส Xcode 9.1 ตอนนี้ใช้AnyObjectแทนclass. protocol AddsMoreCommands: AnyObject where Self: UIViewController { // code }
dodgio

@dodgio ยังคงได้รับคำเตือนเดิมโดยใช้AnyObject
rgkobashi

1
@ DávidPásztorคุณพูดถูก แต่ถ้าคุณต้องการใช้มันในรูปแบบโครงสร้างเช่นการมอบหมายเพื่อให้คุณสมบัติอ่อนแอจำเป็นต้องเพิ่ม´class´ อย่างชัดเจน :)
rgkobashi

48

เนื่องจากปัญหาในคำตอบก่อนหน้านี้ฉันจึงลงเอยด้วยการประกาศนี้:

protocol AddsMoreCommands where Self : UIViewController { 
    // protocol stuff here  
}

ไม่มีคำเตือนใน Xcode 9.1


5
แก้ไขฉันถ้าฉันผิด แต่ปัญหาเกี่ยวกับวิธีแก้ปัญหาข้างต้น (ซึ่งสร้างคำเตือนใน Xcode 9.1 ขึ้นไป) คุณไม่สามารถประกาศว่าผู้รับมอบสิทธิ์อ่อนแอได้หรือไม่?
Kyle Goslan

นอกจากนี้เมื่อผมใช้วิธีนี้กับสวิฟท์ 4.1 ฉันต้องคุณสมบัติหล่อของAddsMoreCommandsการUIViewControllerที่ผมอยากจะหลีกเลี่ยง ...
fl034

9
เพื่อหลีกเลี่ยงการแคสต์คุณสามารถทำได้:typealias AddsMoreCommandsViewController = UIViewController & AddsMoreCommands
พลู

35

ตอนนี้ในSwift 5คุณสามารถทำได้โดย:

protocol AddsMoreCommands: UIViewController {
     /* ... */
}

ค่อนข้างสะดวก


สองตัวนี้ต่างกันอย่างไร? extension AddsMoreCommands ที่ Self: UIViewController {// Code} AND protocol AddsMoreCommands: UIViewController {/ * ... * /} ขอขอบคุณในขั้นสูง
Rahul Patel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.