การนำเข้าโปรโตคอล Swift ในคลาส Objective-C


116

ฉันพยายามที่จะนำเข้าพิธีสาร Swift ชื่อAnalyticProtocolลงในระดับ Objective-C AnalyticFactoryชื่อ

protocol AnalyticProtocol
{

}

ฉันเริ่มต้นจากโปรเจ็กต์ Objective-C ที่มีอยู่ (ฉันไม่ได้สร้างโปรเจ็กต์ Swift ใหม่ด้วย xCode และฉันไม่พบวิธีกำหนดค่าโปรเจ็กต์ Objective-C ของฉันให้เป็นโปรเจ็กต์ Swift ใน xCode 6 )

สวิฟท์ในแฟ้มของฉันฉันรวมถึง.hไฟล์ชื่อMyProjectName-Swift.hแต่กลับมาเรียบเรียงฉันมีข้อผิดพลาดบอกฉันว่ามันไม่ได้อยู่ ฉันจึงสร้าง.hไฟล์ชื่อMyProjectName-Swift.hที่ว่างเปล่า (ฉันไม่รู้ว่าควรใส่อะไรไว้ข้างใน)

ในเอกสารของ Appleพวกเขาบอกว่าฉันต้องรวม.hไฟล์ที่มีชื่อMyProjectName-Swift.hอยู่ใน.mไฟล์ของฉัน แต่ฉันไม่จำเป็นต้องรวมไว้ใน.mไฟล์ของฉันแต่เป็นไฟล์.h. สิ่งนี้อาจเป็นปัญหาได้หรือไม่?

เมื่อฉันพยายามรวบรวมฉันพบข้อผิดพลาดนี้:: 0: error: xxxAnalyticFactory.h: 39: ไม่พบการประกาศโปรโตคอลสำหรับ 'AnalyticProtocol'

และรหัสที่กล่าวหา:

@interface AnalyticFactory : NSObject
{
    Class<AnalyticProtocol> _analyticProtocolClass; // The type of the analytic class currently used.
}

ฉันคิดว่าฉันไม่เข้าใจดีว่าฉันจะนำเข้าโปรโตคอล Swift ไปยังคลาส Objective-C ได้อย่างไร

มีใครเห็นข้อผิดพลาดในสิ่งที่ฉันทำอยู่หรือไม่?


ดูวิดีโอIntegrating Swift with Objective-Cจาก WWDC 2014 ในวิดีโอประมาณ 30:40 น. พวกเขาอธิบายวิธีการเข้าถึงโปรโตคอล Swift ในคลาส Objective-C
Jamie Forrest

คำตอบ:


224

คุณต้องเพิ่ม@objcแอตทริบิวต์ให้กับโปรโตคอล Swift ของคุณดังนี้:

@objc protocol AnalyticProtocol {

}

25
ขอบคุณสำหรับคำตอบ แต่ปัญหายังคงมีอยู่
Jean Lebrument

คุณอาจโพสต์โครงการตัวอย่างที่ทำให้เกิดปัญหาได้หรือไม่
Jamie Forrest

การเพิ่ม @objc ช่วยฉันในการนำเข้าคลาส Swift ไปยัง Obj-C
serg

19
@objc ไม่ได้ผลเสมอไป เมื่อเป็นไปตามโปรโตคอลบางครั้งก็ไม่ได้ผลเมื่อเพิ่มโปรโตคอล@interfaceใน.hไฟล์ อย่างไรก็ตามคุณสามารถเพิ่มโปรโตคอลเป็นส่วนตัว@interfaceใน.mไฟล์และแก้ไขสิ่งต่าง ๆ ได้ (อย่างน้อยก็มีให้ฉันในบางครั้ง) ดังนั้นข้างต้นของคุณมี@implementation @interface MyController() <AnalyticProtocol>
อดัม

1
บางครั้ง Xcode 8 จะบ่นในขณะที่คุณกำลังแก้ไข แต่เมื่อคุณสร้างมันขึ้นมาจริงตามคำตอบนี้พร้อมกับความคิดเห็นข้อผิดพลาดจะหายไป
Roger Pingleton

77

ไม่สามารถนำเข้า Xcode ที่สร้างส่วนหัว Swift ในไฟล์ส่วนหัว objC

ดังนั้นเนื่องจากคุณต้องการใช้ Swift code ในไฟล์ส่วนหัว objC คุณจะต้อง "ส่งต่อประกาศ" คลาสและโปรโตคอลที่คุณต้องการใช้ในไฟล์ส่วนหัว objC ดังนี้:

@protocol AnalyticProtocol;

ตอนนี้คุณสามารถใช้โปรโตคอลในการประกาศคลาส objC ของคุณ:

@interface AnalyticFactory : NSObject
{
    Class<AnalyticProtocol> _analyticProtocolClass; // The type of the analytic class currently used.
}

ในไฟล์การใช้งานของคุณ (ไฟล์ objC .m) คุณสามารถนำเข้าไฟล์ Xcode ที่สร้างขึ้น Swift header ("ProductModuleName-Swift.h") และการใช้งานที่ถูกต้องAnalyticProtocolจะเป็นที่รู้จักสำหรับคอมไพลเลอร์

นอกจากนี้ยังอธิบายไว้ในส่วน "การใช้ Swift จาก Objective-C" ในApple Docs

โปรดทราบว่า XCode จะแจ้งเตือนในไฟล์ส่วนหัว objC เมื่อคุณใช้โปรโตคอลที่ประกาศไปข้างหน้า ("ไม่พบคำจำกัดความของโปรโตคอลสำหรับ 'AnalyticProtocol') แต่สามารถเพิกเฉยได้ - การใช้งานจะพบในเวลาคอมไพล์


19
เหตุใด Xcode จึงแสดงคำเตือนสำหรับโปรโตคอลที่หายไปเมื่อคอมไพล์และทำงานได้ดี วิธีใดในการลบคำเตือน
Oren

ยังไม่สามารถเรียกเมธอดโปรโตคอลในคลาสนี้ได้ จะให้ข้อผิดพลาดNo visible @interface for <ClassName> declares the selector <protocolMethodName>
Elsa

มันสร้างคำเตือนต่อไปนี้: "ไม่พบคำจำกัดความโปรโตคอลสำหรับ xxxx"
JAHelia

51

สำหรับใครก็ตามที่ต้องการใช้โปรโตคอลคุณสามารถทำได้ในสองขั้นตอนโดยไม่ต้องสร้างคำเตือนหรือข้อผิดพลาดใด ๆ :

  1. ใน.swiftไฟล์ของคุณให้เพิ่ม@objcก่อนชื่อโปรโตคอล:

    @objc protocol AnalyticProtocol {
    
    }
  2. ใน.mไฟล์ของคุณนำเข้าส่วนหัว Swift ที่สร้างขึ้นและใช้โปรโตคอลในหมวดหมู่ส่วนตัว (ไฟล์ส่วนหัวตั้งชื่อโดยอัตโนมัติ):

    #import "ProductModuleName-Swift.h"
    
    @interface AnalyticFactory () <AnalyticProtocol>
    
    @end

นี่เป็นแนวทางที่แนะนำของ Apple คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับการผสมและจับคู่ Objective-C และ Swift ได้ที่นี่: https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html


1
ฉันยังคงได้รับคำเตือนพร้อมประกาศล่วงหน้าหรือไม่มี ฉันใช้โปรโตคอลในส่วนขยาย
Cristi Băluță

#import "AnalyticProtocol-Swift.h"ไม่สามารถนำเข้า ดูเหมือนว่า WhateverProtocol-Swift.h จะไม่สร้างขึ้นโดยอัตโนมัติอย่างที่คุณพูด
Hlung

2
สิ่งนี้ได้ผลสำหรับฉัน ไม่มีคำแนะนำหรือคำตอบอื่น ๆ ในหน้านี้ได้ผล ฉันใช้ Swift 4
Poulsbo

1
นี่เป็นวิธีเดียวที่จะลบคำเตือน (แม้ว่าจะใช้งานได้เมื่อโปรโตคอลอยู่ในไฟล์ส่วนหัว)
David P

2
ลิงก์เดียวกันนี้มีอยู่ใน WebArchive: web.archive.org/web/20170310053717/https://developer.apple.com/…
Richard Topchii

3

หากคุณกำลังสร้างกรอบงานจำเป็นต้องนำเข้า

#import "ProductModuleName-Swift.h"

การเปลี่ยนแปลงเป็น:

#import <ProductModuleName/ProductModuleName-Swift.h>

ในกรณีนี้คุณต้องทำให้โปรโตคอลที่รวดเร็วเป็นสาธารณะ :

@objc public protocol AnalyticProtocol {
  func something();
}

3

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

เราสามารถตั้งชื่อโปรโตคอลใหม่ให้มีความหมายมากขึ้นเมื่อใช้ใน Objective C ฉันใช้ "@objc (alias_name)"

นี่คือรหัส Let's have a swift protocol with @objc attribute and alias name to use in the ObjC code.

@objc(ObjTableViewReloadable) protocol TableViewReloadable: class {
   func reloadRow(at index: IndexPath)
   func reloadSection(at index: Int)
   func reloadTable()
}

ตอนนี้ให้ Farword ประกาศโปรโตคอลของเราในไฟล์. h

@protocol ObjTableViewReloadable;

ตอนนี้คุณสามารถปฏิบัติตามโปรโตคอลนี้ในไฟล์. m และเพิ่มการใช้งานวิธีการที่จำเป็น

#import "MyApp-Swift.h"
@interface MyObjcViewController () <ObjTableViewReloadable>

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