ฉันค้นหาบางโพสต์ฉันคิดว่าฉันไม่สามารถเขียนส่วนขยายได้อย่างรวดเร็วและเรียกมันจากรหัส Objective-C ใช่ไหม?
@objc เช่นแอตทริบิวต์รองรับเฉพาะเมธอดคลาสโปรโตคอล?
ฉันค้นหาบางโพสต์ฉันคิดว่าฉันไม่สามารถเขียนส่วนขยายได้อย่างรวดเร็วและเรียกมันจากรหัส Objective-C ใช่ไหม?
@objc เช่นแอตทริบิวต์รองรับเฉพาะเมธอดคลาสโปรโตคอล?
คำตอบ:
คุณสามารถเขียนส่วนขยาย Swift และใช้ในโค้ด Objective-C ทดสอบด้วย XCode 6.1.1
สิ่งที่คุณต้องทำคือ:
สร้างส่วนขยายของคุณใน Swift ( @objc
จำเป็นต้องมีคำอธิบายประกอบตั้งแต่ Swift 4.0.3)
#import "ProjectTarget-Swift.h"
ในคลาส Objective-C ของคุณ (โดยที่ "ProjectTarget" แสดงถึงเป้าหมาย XCode ที่ส่วนขยาย Swift เชื่อมโยงด้วย)
เรียกใช้วิธีการจากส่วนขยาย Swift
ฉันพบว่าในSwift 4.0ฉันต้องเพิ่ม@objc
หน้าคำหลักส่วนขยายของฉันเพื่อให้วิธีการขยาย Swift สามารถมองเห็นได้โดยอินสแตนซ์ของคลาส Objc ที่ฉันกำลังขยาย
ในระยะสั้น:
การตั้งค่าการกำหนดค่าไฟล์:
CustomClass.h
CustomClass.m
CustomClassExtension.swift
ใน CustomClassExtension:
@objc extension CustomClass
{
func method1()
{
...
}
}
ใน AppDelegate.m ของฉัน:
self.customClass = [[CustomClass alloc] init];
[self.customClass method1];
@nonobjc
คำอธิบายประกอบ
การแก้ปัญหานี้ทำงานให้กับสวิฟท์สวิฟท์ 2.2 และ 3 โปรดทราบว่าเฉพาะส่วนขยายสำหรับคลาส (ไม่ใช่สำหรับโครงสร้างหรือ enums) เท่านั้นที่สามารถเข้าถึงได้จาก Objective-C
import UIKit
extension UIColor {
//Custom colours
class func otherEventColor() -> UIColor {
return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
}
}
จากนั้น#import "ProductModuleName-Swift.h"ในไฟล์ ObjC ของคุณ
สวิฟต์ 4
extension UIColor {
// As of Swift 4.0.3, the @objc annotation is needed if you want to use the extension in Objective-C files
@objc
class func otherEventColor() -> UIColor {
return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
}
}
public
จำเป็น? ทำงานได้ดีโดยไม่ต้องpublic
ปรับเปลี่ยนสำหรับฉัน เราสมมติว่าส่วนขยายไม่ได้อยู่ในโครงการเดียวกัน แต่นำเข้าจากโครงการอื่นหรือไม่?
ในฐานะที่เป็นที่กล่าวถึงในคำตอบอื่น ๆ นำเข้าที่สร้างผลงานสวิฟท์ส่วนหัวในกรณีส่วนใหญ่
ข้อยกเว้นคือเมื่อมีการกำหนดหมวดหมู่ในประเภทบริดจ์ (กล่าวคือส่วนขยายถูกกำหนดไว้ที่String
และไม่ใช่NSString
) หมวดหมู่เหล่านี้จะไม่เชื่อมโยงกับ Objective-C โดยอัตโนมัติ ในการแก้ไขปัญหานี้คุณอาจต้องใช้ประเภท Objective-C (และส่งค่าส่งคืนในโค้ด Swift ด้วยas String
) หรือกำหนดส่วนขยายสำหรับทั้งประเภท Swift และ Objective-C
public extension NSString
เช่น หากคุณได้รับตัวระบุที่ไม่ได้รับการแก้ไขหรือข้อผิดพลาดที่คล้ายกันในเวลาคอมไพล์คุณสามารถส่งอีกครั้งกลับไปที่ String เช่นlet sVal = self as String
จากนั้นเรียกรหัสที่จำเป็นบนsVal
mclaughlinj
กล่าวไว้สำหรับทั้งคลาส NSString และ String struct
นำเข้า "#import 'ProductModuleName-Swift.h'ส่วนหัวในวัตถุประสงค์ -c ไฟล์และเพิ่ม@objcหน้าของคุณextentsionในไฟล์ที่รวดเร็ว. มันจะทำงานได้ดีในสวิฟท์ 4.2 และรวดเร็ว 5
หากคิดว่าคุณได้กำหนดค่าทุกอย่างถูกต้อง (ทำเครื่องหมายเอนทิตี Swift ของคุณด้วย @objcMembers หรือ @objc ให้นำเข้าส่วนหัวเชื่อม "ProductModuleName-Swift.h" และอื่น ๆ ) - แต่ยังคงได้รับNo visible @interface for 'FooClass' declares the selector 'fooSelector'
ข้อผิดพลาด:
ตรวจสอบว่าคุณเห็นอินเทอร์เฟซของคุณในส่วนหัวเชื่อมต่อหรือไม่โดยctrl + cmd
คลิกที่อินเทอร์เฟซ หากไม่เป็นเช่นนั้นโปรดดูคำตอบของฉันสำหรับคำถามนี้: ส่วนหัว Swift to Objective-C ไม่มีคลาส Swift