ใน Swift หนึ่งเรียกรหัส Objective-C อย่างไร
Apple กล่าวว่าพวกเขาสามารถอยู่ร่วมในแอปพลิเคชันเดียวได้ แต่นี่หมายความว่าเราสามารถใช้คลาสเก่าที่สร้างขึ้นใหม่ใน Objective-C ในขณะที่สร้างคลาสใหม่ใน Swift ได้หรือไม่
ใน Swift หนึ่งเรียกรหัส Objective-C อย่างไร
Apple กล่าวว่าพวกเขาสามารถอยู่ร่วมในแอปพลิเคชันเดียวได้ แต่นี่หมายความว่าเราสามารถใช้คลาสเก่าที่สร้างขึ้นใหม่ใน Objective-C ในขณะที่สร้างคลาสใหม่ใน Swift ได้หรือไม่
คำตอบ:
หากคุณมีระดับที่มีอยู่ที่คุณต้องการที่จะใช้ดำเนินการขั้นตอนที่ 2และจากนั้นข้ามไปขั้นตอนที่ 5 (สำหรับบางกรณีฉันต้องเพิ่มความชัดเจน
#import <Foundation/Foundation.h
ลงในไฟล์ Objective-C รุ่นเก่ากว่า)
เพิ่มไฟล์ในชั้นเรียนของคุณและชื่อมัน.m
CustomObject.m
เมื่อเพิ่ม.m
ไฟล์คุณอาจโดนพรอมต์ที่มีลักษณะดังนี้:
คลิกใช่ !
หากคุณไม่ได้เห็นข้อความหรือเผลอลบส่วนหัวของการเชื่อมโยงของคุณเพิ่มใหม่ไฟล์โครงการของคุณและชื่อ.h
<#YourProjectName#>-Bridging-Header.h
ในบางสถานการณ์โดยเฉพาะอย่างยิ่งเมื่อทำงานกับกรอบงาน Objective-C คุณจะไม่เพิ่มคลาส Objective-C อย่างชัดเจนและ Xcode ไม่สามารถค้นหาตัวเชื่อมโยงได้ ในกรณีนี้ให้สร้าง.h
ไฟล์ของคุณตามที่ระบุไว้ข้างต้นจากนั้นตรวจสอบให้แน่ใจว่าคุณได้เชื่อมโยงพา ธ ในการตั้งค่าโปรเจ็กต์เป้าหมายดังนี้:
บันทึก:
เป็นวิธีปฏิบัติที่ดีที่สุดในการเชื่อมโยงโครงการของคุณโดยใช้$(SRCROOT)
มาโครดังนั้นหากคุณย้ายโครงการของคุณหรือทำงานกับคนอื่น ๆ โดยใช้ที่เก็บระยะไกลมันจะยังใช้งานได้ $(SRCROOT)
อาจถือได้ว่าเป็นไดเรกทอรีที่มีไฟล์. xcodeproj ของคุณ อาจมีลักษณะเช่นนี้:
$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h
เพิ่มอีกไฟล์และชื่อ.h
CustomObject.h
ใน CustomObject.h
#import <Foundation/Foundation.h>
@interface CustomObject : NSObject
@property (strong, nonatomic) id someProperty;
- (void) someMethod;
@end
ใน CustomObject.m
#import "CustomObject.h"
@implementation CustomObject
- (void) someMethod {
NSLog(@"SomeMethod Ran");
}
@end
ในYourProject-Bridging-Header.h
:
#import "CustomObject.h"
ในSomeSwiftFile.swift
:
var instanceOfCustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
print(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()
ไม่จำเป็นต้องนำเข้าอย่างชัดเจน; นั่นคือสิ่งที่ Bridging header ใช้
เพิ่มไฟล์ในโครงการของคุณและชื่อ.swift
MySwiftObject.swift
ในMySwiftObject.swift
:
import Foundation
@objc(MySwiftObject)
class MySwiftObject : NSObject {
@objc
var someProperty: AnyObject = "Some Initializer Val" as NSString
init() {}
@objc
func someFunction(someArg: Any) -> NSString {
return "You sent me \(someArg)"
}
}
ในSomeRandomClass.m
:
#import "<#YourProjectName#>-Swift.h"
ไฟล์: <#YourProjectName#>-Swift.h
ควรถูกสร้างขึ้นโดยอัตโนมัติในโครงการของคุณแม้ว่าคุณจะไม่เห็นก็ตาม
MySwiftObject * myOb = [MySwiftObject new];
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
myOb.someProperty = @"Hello World";
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
NSString * retString = [myOb someFunctionWithSomeArg:@"Arg"];
NSLog(@"RetString: %@", retString);
หากการเสร็จสิ้นโค้ดไม่ทำงานตามที่คุณคาดหวังให้ลองเรียกใช้งานบิลด์อย่างรวดเร็ว⌘⇧Rเพื่อช่วยให้ Xcode ค้นหาโค้ด Objective-C บางส่วนจากบริบท Swift และในทางกลับกัน
ถ้าคุณเพิ่ม.swift
ไฟล์ไปยังโครงการเก่าและได้รับข้อผิดพลาดdyld: Library not loaded: @rpath/libswift_stdlib_core.dylib
ลองสมบูรณ์รีสตาร์ท Xcode
แม้ว่าในขั้นต้นจะเป็นไปได้ที่จะใช้คลาส Swift ล้วนๆ (ไม่ใช่ส่วนที่สืบทอดNSObject
) ซึ่งสามารถมองเห็นได้ด้วย Objective-C โดยใช้ส่วน@objc
นำหน้า แต่ไม่สามารถทำได้อีกต่อไป ตอนนี้ที่จะมองเห็นได้ใน Objective-C, วัตถุ Swift อย่างใดอย่างหนึ่งจะต้องมีชั้นเรียนที่สอดคล้องกับNSObjectProtocol
(วิธีที่ง่ายที่สุดที่จะทำนี้คือการสืบทอดจากNSObject
) หรือจะเป็นenum
การทำเครื่องหมายที่มีมูลค่าดิบชนิดจำนวนเต็มบางอย่างเช่น@objc
คุณสามารถดูประวัติการแก้ไขสำหรับตัวอย่างโค้ด Swift 1.x ที่ใช้โดยไม่มีข้อ จำกัด เหล่านี้Int
@objc
โปรดดูที่คู่มือของ Apple ที่จะใช้สวิฟท์กับโกโก้และวัตถุประสงค์ -C คู่มือนี้ครอบคลุมถึงวิธีการใช้รหัส Objective-C และ C จาก Swift และในทางกลับกันและมีคำแนะนำสำหรับการแปลงโครงการหรือผสมและจับคู่ Objective-C / C และ Swift ในโครงการที่มีอยู่
คอมไพเลอร์สร้างไวยากรณ์ Swift โดยอัตโนมัติสำหรับการเรียกใช้ฟังก์ชัน C และวิธีการ Objective-C เท่าที่เห็นในเอกสารวัตถุประสงค์ -C นี้:
UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
เปลี่ยนเป็นรหัส Swift นี้:
let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)
Xcode ยังทำการแปลนี้ทันทีคุณสามารถใช้ Open Quickly ในขณะที่แก้ไขไฟล์ Swift และพิมพ์ชื่อคลาส Objective-C และจะนำคุณไปยังส่วนหัวของคลาสเวอร์ชัน Swift-ified (คุณสามารถรับสิ่งนี้ได้โดยการคลิก cmd ที่สัญลักษณ์ API ในไฟล์ Swift) และเอกสารอ้างอิง API ทั้งหมดในiOS 8และOS X v10.10 (Yosemite)ห้องสมุดนักพัฒนาสามารถมองเห็นได้ทั้งใน Objective-C และ Swift แบบฟอร์ม (เช่นUIView
)
นี่คือคำแนะนำทีละขั้นตอนสำหรับการใช้รหัส Objective-C (ในกรณีนี้เป็นเฟรมเวิร์กที่จัดทำโดยบุคคลที่สาม) ในโครงการ Swift:
ในขั้นตอนง่าย ๆ :
ข้อความแจ้งจะปรากฏขึ้นจากนั้นคลิกที่ OK ... หากไม่ปรากฏขึ้นเราจะสร้างขึ้นเองดังต่อไปนี้ ... สร้างไฟล์ส่วนหัวหนึ่งไฟล์จากแหล่ง iOS และตั้งชื่อ ProjectName-Bridging-Header (ตัวอย่าง: ทดสอบ -Bridging-Header) จากนั้นไปที่การสร้างการตั้งค่าในรหัสคอมไพเลอร์ Swift -> Objective-C bridge เพิ่มชื่อ Objective-C bridge .. (Test / Test-Bridging-Header.h) ใช่แล้วเสร็จแล้ว
เลือกลบไฟล์ Objective-C ที่คุณเพิ่ม (ชื่อ "อะไร" ในภาพ GIF ด้านบน) คุณไม่ต้องการมันอีกแล้ว
เปิดไฟล์ส่วนหัวแก้ - ชื่อไฟล์จะอยู่ในรูป[YourProject] -Bridging-Header.h มันรวมถึงการแสดงความคิดเห็นให้ Xcode เพิ่มบรรทัดโค้ดสำหรับไฟล์ Objective-C ที่คุณต้องการรวมเช่นเฟรมเวิร์กของบุคคลที่สาม ตัวอย่างเช่นหากต้องการเพิ่ม Mixpanel ในโครงการของคุณคุณจะต้องเพิ่มบรรทัดของรหัสต่อไปนี้ลงในไฟล์ส่วนหัวการเชื่อมโยง:
#import "Mixpanel.h"
ตอนนี้ในไฟล์ Swift ใด ๆ ที่คุณสามารถใช้รหัส Objective-C ที่มีอยู่ในไวยากรณ์ Swift (ในกรณีของตัวอย่างนี้และคุณสามารถเรียกวิธี Mixpanel SDK และอื่น ๆ ) คุณต้องทำความคุ้นเคยกับวิธีที่ Xcode แปล Objective-C เป็น Swift คำแนะนำของ Appleอ่านได้อย่างรวดเร็ว หรือดูคำตอบนี้สำหรับการสรุปที่ไม่สมบูรณ์
ตัวอย่างสำหรับ Mixpanel:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Mixpanel.sharedInstanceWithToken("your-token")
return true
}
แค่นั้นแหละ!
หมายเหตุ: หากคุณลบไฟล์ส่วนหัวการเชื่อมโยงออกจากโครงการของคุณให้แน่ใจว่าได้เข้าไปในการตั้งค่าการสร้างและลบค่าสำหรับ " ส่วนหัว Bridging-C วัตถุประสงค์ " ภายใต้ "Swift Compiler - การสร้างรหัส"
คุณสามารถอ่านโพสต์ดีสวิฟท์และ Cocoapods โดยทั่วไปเราจำเป็นต้องสร้างไฟล์ส่วนหัวการเชื่อมต่อและวางส่วนหัว Objective-C ทั้งหมดที่นั่น จากนั้นเราต้องอ้างอิงจากการตั้งค่าการสร้างของเรา หลังจากนั้นเราสามารถใช้รหัส Objective-C
let manager = AFHTTPRequestOperationManager()
manager.GET(
"http://example.com/resources.json",
parameters: nil,
success: { (operation: AFHTTPRequestOperation!,
responseObject: AnyObject!) in
println("JSON: " + responseObject.description)
},
failure: { (operation: AFHTTPRequestOperation!,
error: NSError!) in
println("Error: " + error.localizedDescription)
})
ดูเอกสารของ Apple โดยใช้ Swift กับ Cocoa และ Objective-Cด้วย
ฉันเขียนโครงการ Xcode 6 อย่างง่ายที่แสดงวิธีผสม C ++, Objective-C และ Swift code:
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
โดยเฉพาะอย่างยิ่งตัวอย่างเรียก Objective-C และ C ++ ฟังก์ชั่นจากสวิฟท์
กุญแจสำคัญคือการสร้างส่วนหัวที่ใช้ร่วมกัน Project-Bridging-Header.h และวางส่วนหัว Objective-C ไว้ที่นั่น
โปรดดาวน์โหลดโครงการเป็นตัวอย่างที่สมบูรณ์
ฉันขอบคุณมากสำหรับคำตอบของ @ Logan ช่วยได้มากในการสร้างไฟล์บริดจ์และการตั้งค่า
แต่หลังจากทำตามขั้นตอนเหล่านี้แล้วฉันยังไม่ได้รับคลาส Objective-C ใน Swift
ฉันใช้cocoapods
ห้องสมุดและรวมเข้ากับโครงการของฉัน pod "pop"
ซึ่งเป็น
ดังนั้นหากคุณใช้ Objective-C พ็อดใน Swift อาจมีโอกาสที่คุณจะไม่สามารถรับหรือimport
เรียนใน Swift ได้
สิ่งง่าย ๆ ที่คุณต้องทำคือ:
<YOUR-PROJECT>-Bridging-Header
ไฟล์และ#import <ObjC_Framework>
เป็น@import ObjC_Framework
ตัวอย่างเช่น: (ห้องสมุดป๊อป)
แทนที่
#import <pop/POP.h>
กับ
@import pop;
ใช้clang import
เมื่อ#import
ไม่ทำงาน
อ้างจากเอกสาร :
เฟรมเวิร์ก Objective-C ใด ๆ (หรือไลบรารี C) ที่สามารถเข้าถึงได้เนื่องจากโมดูลสามารถนำเข้าสู่ Swift ได้โดยตรง ซึ่งรวมถึงกรอบระบบ Objective-C ทั้งหมด - เช่น Foundation, UIKit และ SpriteKit— รวมถึงไลบรารี C ทั่วไปที่จัดมาให้พร้อมกับระบบ ตัวอย่างเช่นหากต้องการนำเข้า Foundation เพียงเพิ่มคำสั่งนำเข้านี้ไปที่ด้านบนของไฟล์ Swift ที่คุณกำลังใช้งาน:
import Foundation
การนำเข้านี้ทำให้ API พื้นฐานทั้งหมดรวมถึง NSDate, NSURL, NSMutableData และวิธีการคุณสมบัติและหมวดหมู่ทั้งหมดของพวกเขามีให้บริการโดยตรงใน Swift
เพียงแค่ทราบสำหรับใครก็ตามที่พยายามที่จะเพิ่มไลบรารี Objective-C ถึงสวิฟท์: คุณควรเพิ่ม-ObjCในการตั้งค่ารูปร่าง -> การเชื่อมโยง -> ธง Linker อื่น ๆ
หลังจากที่คุณสร้างส่วนหัวของ Bridging ให้ไปที่ Build Setting => ค้นหา "Objective-C Bridging Header"
ด้านล่างคุณจะพบไฟล์ "" ชื่อส่วนหัวของอินเทอร์เฟซที่สร้างขึ้น C "
นำเข้าไฟล์นั้นในตัวควบคุมมุมมองของคุณ
ตัวอย่าง: ในกรณีของฉัน: "Dauble-Swift.h"
คลิกที่ใหม่เมนูไฟล์และเลือกไฟล์เลือกภาษาวัตถุประสงค์ ในเวลานั้นมันจะสร้างไฟล์ "Objective-C Bridging Header" โดยอัตโนมัติซึ่งใช้เพื่อกำหนดชื่อคลาสบางส่วน
"Objective-C Bridging Header" ภายใต้ "Swift Compiler - การสร้างรหัส"
ในโครงการ Swift 4.2.1 ใน Xcode 10.1 คุณสามารถเพิ่มไฟล์ Objective-C ได้อย่างง่ายดาย ทำตามขั้นตอนด้านล่างเพื่อเชื่อมไฟล์ Objective-C กับโครงการ Swift
Step_01: สร้างโครงการ Xcode ใหม่โดยใช้ภาษา Swift:
File
> New
> >Project
objc
Step_02: ในโครงการ Swift เพิ่มไฟล์ Objective-C ใหม่:
File
> New
> File...
> >macOS
Objective-C File
Step_03: หากคุณเพิ่มไฟล์ Objective-C ใหม่ในโครงการ Swift ในครั้งแรก Xcode จะถามคุณ:
Would you like to configure an Objective-C bridging header
?
Step_04: เลือกตัวเลือก:
Create Bridging Header
.
Step_05: ไฟล์ที่เกี่ยวข้องจะถูกสร้างขึ้นด้วยชื่อ:
Objc-Bridging-Header.h
.
Step_06: ตอนนี้คุณต้องตั้งค่าพา ธ ไฟล์ Bridge ในส่วนหัวของบริดจ์ ใน Project Navigator คลิกที่ชื่อโครงการobjc
แล้วเลือก:
Build Settings
> >Objective-C Bridging Header
Objc-Bridging-Header.h
Step_07: ลากแล้วปล่อยของคุณObjc-Bridging-Header.h
ลงในกล่องเพื่อสร้างเส้นทางไฟล์
Step_08: เปิดObjc-Bridging-Header.h
ไฟล์ของคุณและนำเข้าไฟล์ Objective-C ที่คุณต้องการใช้ในไฟล์ Swift ของคุณ
#import "SpecialObjcFile.m"
นี่คือเนื้อหาของSpecialObjcFile.m
:
#import <Foundation/Foundation.h>
@interface Person: NSObject {
@public
bool busy;
}
@property
bool busy;
@end
Step_09: ในไฟล์ Swift ของคุณคุณสามารถใช้คลาส Objective-C:
override func viewDidLoad() {
super.viewDidLoad()
let myObjcContent = Person()
print(myObjcContent.busy)
}
Logans คำตอบที่ทำงานได้ดียกเว้นในรุ่นล่าสุดSwift 5
จะช่วยให้รวบรวมข้อผิดพลาดบางอย่าง นี่คือการแก้ไขสำหรับผู้ที่ทำงานกับ Swift 5
import Foundation
class MySwiftObject : NSObject {
var someProperty: AnyObject = "Some Initializer Val" as AnyObject
override init() {}
func someFunction(someArg:AnyObject) -> String {
let returnVal = "You sent me \(someArg)"
return returnVal
}
}
เพิ่มส่วนหัว.h
และ.m
ไฟล์การใช้งาน- ไฟล์คลาส Cocoa (Objective-C)
ตัวอย่างเช่นMyFileName
กำหนดค่าการเชื่อมต่อส่วนหัว
เมื่อคุณเห็นWould you like to configure an Objective-C bridging header
คลิก - ใช่
<target_name>-Bridging-Header.h
จะถูกสร้างขึ้นโดยอัตโนมัติเพิ่มคลาสให้กับ Bridging-Header
In <target_name>-Bridging-Header.h
เพิ่มบรรทัด#import "<MyFileName>.h"
PS หากคุณควรเพิ่มไฟล์ Objective-C ที่มีอยู่ลงใน Swift project ให้เพิ่มBridging-Header.h
ไว้ล่วงหน้า
เพิ่ม<MyFileName>.swift
และขยายNSObject
นำเข้าไฟล์ Swift ไปที่ ObjC Class
Add#import "<#YourProjectName#>-Swift.h"
ลงในไฟล์ Objective-C ของคุณ
ทำเครื่องหมายรหัส Swift สาธารณะ[@objc และ @objcMembers]
Apple ได้ให้คำแนะนำอย่างเป็นทางการในเอกสารนี้: วิธีการโทรหาวัตถุประสงค์ -c-code-from-swift
นี่คือส่วนที่เกี่ยวข้อง:
ที่จะนำเข้าชุดของแฟ้ม Objective-C ลงในรหัส Swift ภายในเป้าหมายแอปเดียวกันคุณพึ่งพาObjective-C แก้ไฟล์ส่วนหัวเพื่อแสดงไฟล์เหล่านั้นไปยังสวิฟท์ Xcode เสนอให้สร้างส่วนหัวนี้เมื่อคุณเพิ่มไฟล์ Swift ไปยังแอป Objective-C ที่มีอยู่หรือไฟล์ Objective-C ไปยังแอป Swift ที่มีอยู่
หากคุณยอมรับ Xcode จะสร้างไฟล์ส่วนหัวการเชื่อมโยงพร้อมกับไฟล์ที่คุณกำลังสร้างและตั้งชื่อโดยใช้ชื่อโมดูลผลิตภัณฑ์ของคุณตามด้วย "-Bridging-Header.h" หรือคุณสามารถสร้างส่วนหัวการเชื่อมโยงตัวเองโดยเลือกไฟล์> ใหม่> ไฟล์> [ระบบปฏิบัติการ]> ที่มา> ไฟล์ส่วนหัว
แก้ไขส่วนหัว bridging เพื่อแสดงรหัส Objective-C ของคุณเป็นรหัส Swift ของคุณ:
ส่วนหัว Objective-C สาธารณะใด ๆ ที่ระบุไว้ในส่วนหัวการเชื่อมต่อจะปรากฏต่อ Swift
วิธีการสองวิธีในการใช้วัตถุประสงค์ -c
1
2
ดีไปแล้ว ขอบคุณ