Làm cách nào để gọi mã Objective-C từ Swift?


974

Trong Swift, làm thế nào để gọi mã Objective-C?

Apple đã đề cập rằng họ có thể cùng tồn tại trong một ứng dụng, nhưng điều này có nghĩa là người ta có thể sử dụng lại các lớp cũ được tạo trong Objective-C trong khi xây dựng các lớp mới trong Swift?


13
Xem hướng dẫn của Apple về Sử dụng Swift với Ca cao và Mục tiêu-C .
gà trống


10
Điều thú vị là câu hỏi này nhận được rất nhiều sự ủng hộ và tiền thưởng. Khi tôi lần đầu tiên nhìn thấy nó, tôi chỉ nghĩ: RTFM. Như được đặt ra, nó thực sự cho thấy không có nghiên cứu nào vì hiện tại chỉ có hai hoặc ba tài nguyên chính thức ghi nhận Swift, và một trong số đó hoàn toàn dành riêng cho chính xác điều này (và được liên kết trong bình luận đầu tiên).
Tệp tương tự

6
@EvolGate: chính xác những gì còn thiếu từ Objective C ngăn nó trở thành ngôn ngữ độc lập với nền tảng? Ngôn ngữ và các thư viện tiêu chuẩn ngôn ngữ là nguồn mở. Bạn có thể sử dụng Objective C trong và cho Windows, Os X, Linux, BSD, Solaris và bất kỳ nền tảng nào khác được hỗ trợ bởi GCC hoặc LLVM. Bạn có thể dễ dàng chuyển Objective C sang bất kỳ nền tảng nào với trình biên dịch C đàng hoàng ngay cả khi nó được hỗ trợ bởi cả GCC và LLVM. Tôi không thấy làm thế nào nó có thể độc lập hơn nền tảng này.
Tệp tương tự

2
@DavidMulder: Phần "Lý do" có còn cần thiết không?
franck

Câu trả lời:


1395

Sử dụng các lớp Objective-C trong Swift

Nếu bạn có một lớp hiện có mà bạn muốn sử dụng, hãy thực hiện Bước 2 và sau đó chuyển sang Bước 5 . (Đối với một số trường hợp, tôi đã phải thêm một #import <Foundation/Foundation.htệp rõ ràng vào Tệp Mục tiêu-C cũ hơn.)

Bước 1: Thêm triển khai Objective-C - .m

Thêm một .mtập tin vào lớp của bạn và đặt tên cho nó CustomObject.m.

Bước 2: Thêm tiêu đề bắc cầu

Khi thêm .mtệp của bạn , bạn có thể sẽ gặp phải một dấu nhắc giống như thế này:

Hộp thoại kiểu macOS từ Xcode hỏi bạn có muốn "định cấu hình tiêu đề bắc cầu Objective-C không"

Nhấp vào !

Nếu bạn không thấy lời nhắc hoặc vô tình xóa tiêu đề bắc cầu của mình, hãy thêm một .htệp mới vào dự án của bạn và đặt tên cho nó <#YourProjectName#>-Bridging-Header.h.

Trong một số trường hợp, đặc biệt là khi làm việc với các khung Objective-C, bạn không thêm một lớp Objective-C một cách rõ ràng và Xcode không thể tìm thấy trình liên kết. Trong trường hợp này, hãy tạo .htệp của bạn có tên như đã đề cập ở trên, sau đó đảm bảo bạn liên kết đường dẫn của tệp đó trong cài đặt dự án của mục tiêu như sau:

Một hình ảnh minh họa đoạn văn trên

Ghi chú:

Đó là cách tốt nhất để liên kết dự án của bạn bằng cách sử dụng $(SRCROOT)macro để nếu bạn di chuyển dự án của mình hoặc làm việc với dự án đó bằng kho lưu trữ từ xa, nó vẫn sẽ hoạt động. $(SRCROOT)có thể được coi là thư mục chứa tệp .xcodeproj của bạn. Nó có thể trông như thế này:

$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h

Bước 3: Thêm tiêu đề Objective-C - .h

Thêm một .htập tin khác và đặt tên cho nó CustomObject.h.

Bước 4: Xây dựng lớp Objective-C của bạn

Trong CustomObject.h

#import <Foundation/Foundation.h>

@interface CustomObject : NSObject

@property (strong, nonatomic) id someProperty;

- (void) someMethod;

@end

Trong CustomObject.m

#import "CustomObject.h"

@implementation CustomObject 

- (void) someMethod {
    NSLog(@"SomeMethod Ran");
}

@end

Bước 5: Thêm Class vào Bridging-Header

Trong YourProject-Bridging-Header.h:

#import "CustomObject.h"

Bước 6: Sử dụng đối tượng của bạn

Trong SomeSwiftFile.swift:

var instanceOfCustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
print(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()

Không cần phải nhập một cách rõ ràng; đó là những gì tiêu đề cầu nối dành cho.

Sử dụng các lớp Swift trong Objective-C

Bước 1: Tạo lớp Swift mới

Thêm một .swifttập tin vào dự án của bạn và đặt tên cho nó MySwiftObject.swift.

Trong 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)"
    }
}

Bước 2: Nhập tệp Swift vào lớp ObjC

Trong SomeRandomClass.m:

#import "<#YourProjectName#>-Swift.h"

Tệp: <#YourProjectName#>-Swift.hnên đã được tạo tự động trong dự án của bạn, ngay cả khi bạn không thể nhìn thấy nó.

Bước 3: Sử dụng lớp học của bạn

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);

Ghi chú:

  1. Nếu Hoàn thành mã không hoạt động như bạn mong đợi, hãy thử chạy bản dựng nhanh Rđể giúp Xcode tìm một số mã Objective-C từ ngữ cảnh Swift và ngược lại.

  2. Nếu bạn thêm một .swifttệp vào một dự án cũ hơn và gặp lỗi dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib, hãy thử khởi động lại hoàn toàn Xcode .

  3. Mặc dù ban đầu có thể sử dụng các lớp Swift thuần túy (Không phải hậu duệ NSObject) mà Objective-C hiển thị bằng cách sử dụng @objctiền tố, nhưng điều này không còn có thể. Bây giờ, để hiển thị trong Objective-C, đối tượng Swift phải là một lớp tuân theo NSObjectProtocol(cách dễ nhất để làm điều này là kế thừa từ NSObject) hoặc được enumđánh dấu @objcbằng một giá trị thô của một số loại số nguyên như Int. Bạn có thể xem lịch sử chỉnh sửa để biết ví dụ về mã Swift 1.x bằng cách sử dụng @objcmà không có những hạn chế này.


5
Điều quan trọng là bạn cần chú thích các phương thức với các phương thức @objc hoặc Swift sẽ không hiển thị từ Objective-C.
Tomáš Linhart

29
Bạn đúng rồi. Bạn chỉ cần chỉ định nó nếu bạn không sử dụng các đối tượng Ca cao. Để có thể truy cập và sử dụng được trong Objective-C, một lớp Swift phải là hậu duệ của lớp Objective-C hoặc nó phải được đánh dấu @objc.
Tomáš Linhart


2
Xem thêm: WWDC 2014 Phiên 406: Tích hợp Swift với Objective-C
Stuart M

6
Nếu nhập khung công tác Objective C vào Swift, hãy đảm bảo nhập tất cả các khung mà khung Obj C phụ thuộc vào dự án của bạn (trong Giai đoạn xây dựng -> Liên kết nhị phân với thư viện), sau đó thêm # import cho những tệp đó vào tệp tiêu đề tiền tố, phải được thêm vào dự án của bạn trong cài đặt bản dựng (trong trường Tiêu đề tiền tố). Điều này bao gồm các khung như UIKit và Foundation, ngay cả khi các khung đã được sử dụng từ bên trong Swift. Điều này làm tôi vấp ngã trong nhiều giờ, và dường như không ai ghi lại các bước này.
dùng1021430

121

Xem hướng dẫn của Apple về Sử dụng Swift với Ca cao và Mục tiêu-C . Hướng dẫn này bao gồm cách sử dụng mã Objective-C và C từ Swift và ngược lại và có các đề xuất về cách chuyển đổi dự án hoặc trộn và khớp các phần Objective-C / C và Swift trong dự án hiện có.

Trình biên dịch tự động tạo cú pháp Swift để gọi các hàm C và các phương thức Objective-C. Như đã thấy trong tài liệu, Mục tiêu-C này:

UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];

biến thành mã Swift này:

let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)

Xcode cũng thực hiện bản dịch này một cách nhanh chóng - bạn có thể sử dụng Mở nhanh trong khi chỉnh sửa tệp Swift và nhập tên lớp Objective-C và nó sẽ đưa bạn đến phiên bản tiêu đề của Swift. (Bạn cũng có thể có được điều này bằng cách nhấp vào cmd vào biểu tượng API trong tệp Swift.) Và tất cả tài liệu tham khảo API trong thư viện dành cho nhà phát triển iOS 8OS X v10.10 (Yosemite) có thể nhìn thấy trong cả Objective-C và Swift các hình thức (ví dụ UIView).


3
Liên kết trực tiếp đến tài liệu của Apple về cách tích hợp Swift trong dự án hiện có: developer.apple.com/l
Library / prelelease / ios / document / Swift / trộm

Nếu chúng tôi quan tâm đến lý do tại sao các tệp tiêu đề lại cần thiết và cách sử dụng nó trong giai đoạn liên kết, thì hãy đảm bảo bạn đã đọc Hướng dẫn Swift này: Tìm hiểu về Đường ống xây dựng Swift / Objective-C
Honey

62

Dưới đây là các hướng dẫn từng bước để sử dụng mã Objective-C (trong trường hợp này là khung do bên thứ ba cung cấp) trong dự án Swift:

  1. Thêm bất kỳ tệp Objective-C nào vào dự án Swift của bạn bằng cách chọn Tệp -> Mới -> Tệp mới -> Tệp Objective-C. Khi lưu, Xcode sẽ hỏi bạn có muốn thêm tiêu đề bắc cầu không . Chọn ' '. (nguồn: derrrick.com )Gif: thêm tệp trống vào dự án và tạo tiêu đề bắc cầu

Trong các bước đơn giản:

  1. Một dấu nhắc xuất hiện, rồi bấm vào OK ... Nếu nó không xuất hiện, thì chúng tôi tạo nó theo cách thủ công như sau ... Tạo một tệp tiêu đề từ nguồn iOS và đặt tên ProjectName-Bridging-Header (ví dụ: Kiểm tra -Bridging-Header), sau đó chuyển đến cài đặt xây dựng trong mã trình biên dịch Swift -> Cầu Objective-C thêm tên cầu Objective-C .. (Test / Test-Bridging-Header.h). Vâng, nó đã hoàn thành.

  2. Hoặc bạn có thể xóa tệp Objective-C mà bạn đã thêm (được đặt tên là "bất cứ thứ gì" trong ảnh GIF ở trên). Bạn không cần nó nữa.

  3. Mở tệp tiêu đề bắc cầu - tên tệp có dạng [YourProject] -Bridging-Header.h . Nó bao gồm một nhận xét do Xcode cung cấp. Thêm một dòng mã cho tệp Objective-C mà bạn muốn đưa vào , chẳng hạn như khung của bên thứ ba. Ví dụ: để thêm Mixpanel vào dự án của bạn, bạn sẽ cần thêm dòng mã sau vào tệp tiêu đề bắc cầu:

    #import "Mixpanel.h"
  4. Bây giờ trong bất kỳ tệp Swift nào, bạn có thể sử dụng mã Objective-C hiện có, theo cú pháp Swift (trong trường hợp của ví dụ này và bạn có thể gọi các phương thức SDK Mixpanel, v.v.). Bạn cần làm quen với cách Xcode dịch Objective-C sang Swift. Hướng dẫn của Apple là đọc nhanh. Hoặc xem câu trả lời này cho một bản tóm tắt không đầy đủ.

Ví dụ cho Mixpanel:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    Mixpanel.sharedInstanceWithToken("your-token")
    return true
}

Đó là nó!

Lưu ý: Nếu bạn xóa tệp tiêu đề bắc cầu khỏi dự án của mình , hãy chắc chắn đi vào Cài đặt bản dựng và xóa giá trị cho " Tiêu đề cầu nối khách quan-C " trong "Trình biên dịch Swift - Tạo mã".


39

Bạn có thể đọc bài viết hay của Swift & Cocoapods . Về cơ bản, chúng ta cần tạo một tệp tiêu đề bắc cầu và đặt tất cả các tiêu đề Objective-C ở đó. Và sau đó chúng ta cần tham chiếu nó từ cài đặt xây dựng của chúng tôi. Sau đó, chúng ta có thể sử dụng mã 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)
  })

Cũng có một cái nhìn về tài liệu của Apple Sử dụng Swift với Ca cao và Objective-C .



24

Một điều nữa tôi muốn thêm vào đây:

Tôi rất biết ơn câu trả lời của @ Logan. Nó giúp rất nhiều để tạo một tập tin cầu nối và thiết lập.

Nhưng sau khi thực hiện tất cả các bước này, tôi vẫn không nhận được lớp Objective-C trong Swift.

Tôi đã sử dụng cocoapodsthư viện và tích hợp nó vào dự án của tôi. Đó là pod "pop".

Vì vậy, nếu bạn đang sử dụng các nhóm Objective-C trong Swift thì có thể bạn không thể có được hoặc importcác lớp vào Swift.

Điều đơn giản bạn phải làm là:

  1. Đi đến <YOUR-PROJECT>-Bridging-Headertập tin và
  2. Thay thế câu lệnh #import <ObjC_Framework>thành@import ObjC_Framework

Ví dụ: (Thư viện nhạc pop)

Thay thế

#import <pop/POP.h>

với

@import pop;

Sử dụng clang importkhi #importkhông hoạt động.


Sử dụng nhập clang khi #import không hoạt động. gì? Không chỉ nói rằng chúng ta nên sử dụng @import?!
Mật ong

22

Trích dẫn từ tài liệu :

Bất kỳ khung Objective-C (hoặc thư viện C) nào có thể truy cập dưới dạng mô-đun đều có thể được nhập trực tiếp vào Swift. Điều này bao gồm tất cả các khung hệ thống Objective-C như Foundation, UIKit và SpriteKit, cũng như các thư viện C phổ biến được cung cấp cùng với hệ thống. Ví dụ: để nhập Foundation, chỉ cần thêm câu lệnh nhập này vào đầu tệp Swift bạn đang làm việc:

import Foundation

Việc nhập này làm cho tất cả các API Foundation Foundation bao gồm NSDate, NSURL, NSMutableData và tất cả các phương thức, thuộc tính và danh mục của họ có sẵn trực tiếp trong Swift.


12

Chỉ cần một lưu ý cho bất cứ ai đang cố gắng thêm thư viện Objective-C vào Swift: Bạn nên thêm -ObjC trong Cài đặt bản dựng -> Liên kết -> Cờ liên kết khác .


Tại sao? Vui lòng thêm thông tin về những gì cờ này làm và tại sao nó nên được thêm vào.
Johan Karlsson

9

Sau khi bạn tạo tiêu đề Cầu nối, hãy chuyển đến Cài đặt xây dựng => Tìm kiếm "Tiêu đề cầu nối khách quan-C".

Ngay bên dưới, bạn sẽ tìm thấy tệp "" Tên tiêu đề giao diện được tạo mục tiêu-C ".

Nhập tệp đó trong trình điều khiển xem của bạn.

Ví dụ: Trong trường hợp của tôi: "Da nát-Swift.h"

mô tả hình ảnh eEter ở đây


5

Nhấp vào menu Tệp mới và chọn tệp chọn ngôn ngữ Mục tiêu. Vào thời điểm đó, nó sẽ tự động tạo ra một tệp "Objective-C Bridging Header" được sử dụng để xác định một số tên lớp.

"Tiêu đề cầu nối khách quan-C" trong "Trình biên dịch Swift - Tạo mã".


3
  1. Tạo tệp .h từ NewFile -> Nguồn -> tệp tiêu đề
  2. Sau đó lưu tên tệp Your_Target_Name-Bridging-Header.h Mọi người ở đây mắc lỗi phổ biến bằng cách lấy tên dự án của họ nhưng đó phải là tên Target của Project nếu trong trường hợp cả hai đều khác nhau, nói chung chúng giống nhau.
  3. Sau đó, trong cài đặt xây dựng tìm kiếm cờ Tiêu đề Cầu nối Objective-C và đặt địa chỉ của tệp cầu nối mới tạo của bạn, bạn có thể nhấp chuột phải vào tệp -> hiển thị trong công cụ tìm -> kéo tệp vào vùng văn bản sau đó địa chỉ sẽ được dân cư.
  4. Sử dụng #import Your_Objective-C_file.h
  5. Trong tệp swift, bạn có thể truy cập tệp ObjC nhưng chỉ bằng ngôn ngữ swift.


3

Trong dự án Swift 4.2.1 trong Xcode 10.1, bạn có thể dễ dàng thêm tệp Objective-C. Thực hiện theo các bước bên dưới để kết nối tệp Objective-C với dự án Swift.

Bước_01: Tạo dự án Xcode mới bằng ngôn ngữ Swift:

File> New> Project> objc.

Step_02: Trong dự án Swift thêm tệp Objective-C mới:

File> New> File...> macOS> Objective-C File.

Bước_03: Nếu bạn thêm tệp Objective-C mới vào dự án Swift ngay lần đầu tiên, Xcode sẽ hỏi bạn:

Would you like to configure an Objective-C bridging header?

nhập mô tả hình ảnh ở đây

Bước_04: Chọn tùy chọn:

Create Bridging Header.

Bước_05: Một tệp tương ứng sẽ được tạo với tên:

Objc-Bridging-Header.h.

nhập mô tả hình ảnh ở đây

Bước_06: Bây giờ, bạn cần thiết lập đường dẫn tệp Bridge trong tiêu đề cầu. Trong Project Navigator, nhấp vào dự án có tên objcvà sau đó chọn:

Build Settings> Objective-C Bridging Header> Objc-Bridging-Header.h.

Bước_07: Kéo và thả của bạn Objc-Bridging-Header.hvào ô đó để tạo đường dẫn tệp.

nhập mô tả hình ảnh ở đây

Bước_08: Mở Objc-Bridging-Header.htệp của bạn và nhập tệp Objective-C mà bạn muốn sử dụng trong tệp Swift của mình.

#import "SpecialObjcFile.m"

Đây là một nội dung của SpecialObjcFile.m:

#import <Foundation/Foundation.h>

@interface Person: NSObject {
@public
    bool busy;
}
@property
    bool busy;
@end

Step_09: Bây giờ trong tệp Swift của bạn, bạn có thể sử dụng lớp Objective-C:

override func viewDidLoad() {
    super.viewDidLoad()
    let myObjcContent = Person()
    print(myObjcContent.busy)
}

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây


1

Logans trả lời hoạt động tốt, ngoại trừ mới nhấtSwift 5 nó cung cấp một số lỗi trình biên dịch. Đây là bản sửa lỗi cho những người đang làm việc trên 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
    }
}

1

Người tiêu dùng Swift, nhà sản xuất Objective-C

  1. Thêm tiêu đề .h.mtệp thực hiện - Tệp lớp ca cao (Objective-C)
    Ví dụMyFileName

  2. cấu hình tiêu đề bắc cầu
    Khi bạn thấy Would you like to configure an Objective-C bridging headernhấp -

    • <target_name>-Bridging-Header.h sẽ được tạo tự động
    • Xây dựng cài đặt -> Tiêu đề cầu nối Objective-C
  3. Thêm Class để Bridging-Header
    Trong <target_name>-Bridging-Header.hthêm một dòng#import "<MyFileName>.h"

PS Nếu bạn nên thêm các tệp Objective-C hiện có vào dự án Swift thêm Bridging-Header.htrước

Người tiêu dùng Objective-C, nhà sản xuất Swift

  1. Thêm một <MyFileName>.swiftvà mở rộngNSObject

  2. Nhập tệp Swift vào lớp ObjC
    Thêm #import "<#YourProjectName#>-Swift.h"vào tệp Objective-C của bạn

  3. Đánh dấu mã Swift công khai [@objc và @objcMembers]


0

Apple đã cung cấp hướng dẫn chính thức trong tài liệu này: how-to-call-aim-c-code-from-swift

Đây là phần có liên quan:

Để nhập một tập hợp các tệp Objective-C vào mã Swift trong cùng một mục tiêu ứng dụng, bạn dựa vào tệp tiêu đề bắc cầu Objective-C để hiển thị các tệp đó cho Swift . Xcode cung cấp để tạo tiêu đề này khi bạn thêm tệp Swift vào ứng dụng Objective-C hiện có hoặc tệp Objective-C vào ứng dụng Swift hiện có.

Nếu bạn chấp nhận, Xcode sẽ tạo tệp tiêu đề bắc cầu cùng với tệp bạn đang tạo và đặt tên cho nó bằng cách sử dụng tên mô-đun sản phẩm của bạn theo sau là "-Bridging-Header.h". Ngoài ra, bạn có thể tự tạo một tiêu đề bắc cầu bằng cách chọn Tệp> Mới> Tệp> [hệ điều hành]> Nguồn> Tệp tiêu đề

Chỉnh sửa tiêu đề bắc cầu để hiển thị mã Objective-C của bạn thành mã Swift:

  1. Trong tiêu đề bắc cầu Objective-C của bạn, nhập mọi tiêu đề Objective-C mà bạn muốn hiển thị cho Swift .
  2. Trong Cài đặt bản dựng, trong Trình biên dịch Swift - Tạo mã, hãy đảm bảo cài đặt bản dựng tiêu đề cầu nối Objective-C có đường dẫn đến tệp tiêu đề bắc cầu. Đường dẫn phải liên quan đến dự án của bạn, tương tự như cách đường dẫn Info.plist của bạn được chỉ định trong Cài đặt bản dựng. Trong hầu hết các trường hợp, bạn sẽ không cần phải sửa đổi cài đặt này.

Bất kỳ tiêu đề Objective-C công khai nào được liệt kê trong tiêu đề bắc cầu đều hiển thị với Swift.


0

Cách tiếp cận hai cách để sử dụng object-c object-c

1

  1. Tạo tệp cầu-header.h trong Dự án Xcode
  2. nhập tệp .h trong tệp Bridge-Header
  3. Đặt đường dẫn của tiêu đề cầu trong Cài đặt bản dựng.
  4. Làm sạch dự án

2

  1. Tạo các tệp object-c trong dự án (nó tự động đặt đường dẫn trong Cài đặt bản dựng cho bạn)
  2. nhập tệp .h trong tệp Bridge-Header

Bây giờ tốt để đi Cảm ơn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.