Gọi hàm Swift từ lớp Objective-C


84

Tôi có một dự án Objective-C cũ và tôi muốn gọi hàm và đối tượng Swift mới, tôi đã tạo tệp " <ProjectName>-Bridging-Header.h" và " <ProjectName>-Swift.h"

Tôi đã dễ dàng gọi hàm từ Swift sang Objective-C nhưng tôi gặp sự cố khi làm ngược lại.

Vì vậy, tôi đã tạo một lớp đơn giản "System.Swift"

import Foundation

@objc class System : NSObject {

    @objc func printSome() {
        println("Print line System");
    }
    
}

bây giờ tôi đã thử làm theo tài liệu ở đây và bên trong <...>-Swift.htệp tôi đã viết điều này

@class System;

@interface System : NSObject

-(void)printSome;

@end

và tôi đã nhập nó vào bên trong Objective-C Class của mình. Tại thời điểm này, bên trong lớp Objective C (hiện tại là UIViewController) của mã Objective-C, tôi đã thử gọi phương thức "printSome":

- (void)viewDidLoad
{
    [super viewDidLoad];
    System * sis = [[System alloc] init];
    [sis printSome];
    //any additional setup after loading the view from its nib.
}

bây giờ tôi gặp lỗi sau:

Các ký hiệu không xác định cho kiến ​​trúc i386: " OBJC_CLASS $ _System", được tham chiếu từ: objc-class-ref trong "ObjectiveC_Class_That_Call_Swift_Object". O ld: symbol (s) not found for architecture i386 clang: error: lệnh linker bị lỗi với mã thoát 1 (sử dụng -v để xem lời gọi)


Bạn có một lỗi trình liên kết. Có phải: (1) Xcode sử dụng tên mô-đun sản phẩm của bạn — không phải tên mục tiêu của bạn — khi đặt tên cho tiêu đề bắc cầu Objective-C và tiêu đề được tạo cho mã Swift của bạn hay (2) đảm bảo nhập tiêu đề Objective-C cho những trước khi nhập tiêu đề được tạo Swift vào tệp Objective-C .m mà bạn muốn truy cập mã Swift từ đó? Bạn có: #import “ProductModuleName-Swift.h” trong mã Objective-C của mình không?
petert

Có, tôi có đọc tài liệu và tên của "ProductModelName" là currect ... Có một lỗi trong xây dựng Thiết lập mô hình sản phẩm không được thiết lập ... tôi thậm chí còn thiết lập nó ...
Eloreden

@petert bạn có thể giải thích rõ hơn điểm thứ hai không? Tôi wrote everithing tôi đã làm ...
Eloreden

Sự cố đã được giải quyết, tôi đã thêm một tệp .h mới trong cuộc gọi dự án của tôi <ProductModelName> -Swift.h nhưng điều này là không cần thiết vì trình biên dịch chỉ tạo đối tượng này ngay cả khi tôi không thể nhìn thấy nó. Tôi đã xóa tệp mới mà tôi đã tạo và bây giờ tất cả đều chạy hoàn hảo. Tnx petert
Eloreden

Bạn có thể trả lời câu hỏi của chính mình - nó có thể giúp ích cho người khác.
petert

Câu trả lời:


50

Sự cố đã được giải quyết, trước đây tôi đã tạo và bao gồm một .htệp mới trong lớp Objective-C của tôi có tên <ProductModuleName>-Swift.hnhưng, như tôi đã phát hiện ra sau đó, bước này là không cần thiết vì trình biên dịch tạo tệp cần thiết không nhìn thấy.

Chỉ cần đưa <ProductModuleName>-Swift.hvào lớp học của bạn và nó sẽ hoạt động.


3
làm thế nào về các chức năng với các tham số?
Arnlee Vizcayno

3
Tôi không thể truy cập các hàm Swift có tham số và giá trị trả về, cũng như không thể truy cập các hàm Swift không có tham số và không có giá trị trả về. Tôi không biết tại sao. Lớp Swift của tôi là một NSObject, tôi đã nhập khuôn khổ Foundation, lớp và các hàm có @objctiền tố. Các -Swift.hđã được tự động tạo ra. Điều làm tôi đau đầu là tôi có thể gọi chính Class nhưng không có bất kỳ chức năng nào bên trong nó. Có ai biết tại sao không?
David Gölzhäuser


2
Nó là <productModuleName>-.Swift.h(không model).
SwiftArchitect

2
Nếu tên sản phẩm của bạn có bất kỳ dấu cách trong nó, thay thế bằng dấu gạch dưới, như: #import "My_Project-Swift.h".
EricRobertBrewer

41

nó là lạ nhưng nó sẽ hoạt động

1) Add @objc  to  Swift class

2) Add in .m 
    #import "(ProjectName)-Swift.h"

3) Call from .h
    @class SwiftClass;

4)On SwiftClass 
   click "Command" + Left Click (Apple Documantation)

5) To see "-Swift.h" -> click "Command" + Left Click

Ứng dụng sẽ tạo giao diện cho lớp này trong -Swift.h

Ví dụ: SWIFT_CLASS ("_ TtC10Project17220PLHelper") @interface PLHelper

  • (void) InformForDownloading: (NSDictionary *) userInfo;
  • (instancetype) init OBJC_DESIGNATED_INITIALIZER; @kết thúc

Bạn cũng có thể ghi đè lên tên obj-C của lớp Swift của bạn sử dụng@objc (MyClassName)
nielsbot

12
Đối với bất kỳ ai có thể mắc phải sai lầm ngớ ngẩn như tôi. Trong bước 2, hãy chắc chắn rằng bạn sử dụng (ProjectName)-Swift.h, KHÔNG (ClassName)-Swift.h !
Hlung

cảm ơn @Svitlana, không thể tin được, nó đã hoạt động !!! Nhưng tôi phải thử lại nhiều lần các bước này, bao gồm cả việc di chuyển các phương thức đã thêm của tôi sang các vị trí khác trong lớp.
Scofield Tran

1
3) @class SwiftClassName;đã cứu tôi
Mazen Kasser

33

Giả sử Chúng ta có ProjectName "MyFirstProjectOnSwift" và tên lớp nhanh "mySwiftClass" và lớp mục tiêu là "MyObjectiveCLass"

Các bước sau là: -

  1. Thêm #import "MyFirstProjectOnSwift-Swift.h" trong "MyObjectiveCLass.m"

  2. Thêm @class mySwiftClass trong MyObjectiveCLass.h;

  3. Sau đó, trong MyObjectiveCLass.m

    mySwiftClass * myClass = [mySwiftClass mới]; {Gọi như thế này trong bất kỳ phương thức nào bạn muốn gọi phương thức nhanh.}

  4. [myClass methodName];


2
mySwiftClass * myClass = [mySwiftClass mới] nó không hoạt động với tôi >>>>>
Hari Narayanan

@HariNarayanan Không nên như vậy, bạn hãy nghĩ dữ liệu có nguồn gốc rõ ràng và mở lại dự án của bạn.
Anubhav Giri

12

Kiểm tra tệp -Swift.h có nhập vào tệp .m của bạn trong mục tiêu-C:

#import <YourProjectName-Swift.h>

Nhấp vào dòng đó và nhấp chuột trái - Chuyển sang Định nghĩa.

Tệp này phải được đưa vào tự động, không phải theo cách thủ công.


2

Nếu bạn vẫn không thấy lớp của mình ngay cả sau khi nhập <ProductModuleName>-Swift.h.

Đảm bảo rằng lớp của bạn đang phân lớp con một lớp bản địa (ví dụ UIViewController) hoặc ít nhất nếu nó chỉ là một lớp tiện ích, hãy đặt nó thành lớp con NSObject. Lớp học của bạn bây giờ sẽ hiển thị.


2

Mẹo nhỏ bổ sung cho bất kỳ ai tình cờ gặp bài đăng này và đối với hwhom, các câu trả lời khác không hoạt động: bạn cũng có thể phải khai báo lớp Swift của mình là "công khai".

Thí dụ:

@objc public class MySwiftClass: NSObject {


0

Cách được đề xuất để thực thi mã Swift từ Objective-C trên các dự án đang được chuyển từ Obj-C sang Swift là sử dụng mẫu Bridge / Proxy.

  1. Thực hiện Bridge.

import Foundation

@objc class AnalyticsPropertyBridge: NSObject {

private var analytics: AnalyticsManager = AnalyticsManager()

@objc func refreshProperties() {

    self.analytics.set(AnalyticsProperty.clientType)
}

}

  1. Bao gồm mô-đun trình gọi objC trong tệp ô (Bridging-Header):

#import "CallerModule.h"

  1. Cuối cùng trong tệp .m của người gọi, hai vấn đề:

3.a Nhập tệp ô:

#import "MyProject-Swift.h"

3.b Gọi cầu.

[[AnalyticsPropertyBridge new] refreshProperties];

Lợi ích: Mã nhanh của bạn sẽ không bị dính @objc vì mã đang được gọi từ Objc. Theo thời gian, objC sẽ bị giảm trong dự án của bạn và cuối cùng cô dâu sẽ bị loại bỏ.


-1

Một bài báo tốt ở đây nếu ai đó vẫn còn vấn đề.

Thiết lập khả năng tương tác Swift và Objective-C

  1. Bài viết này thảo luận chuyên sâu về cách nhập tệp Swift vào ObjC cũng như tệp objc sang Swift.
  2. Nó cũng giải quyết một vấn đề thường gặp phải khi tên Dự án có khoảng trống trong đó.
  3. Nó cũng thảo luận về cờ "Tên mô-đun sản phẩm".

Mặc dù về mặt lý thuyết, điều này có thể trả lời câu hỏi, nhưng tốt hơn hết bạn nên đưa các phần thiết yếu của câu trả lời vào đây và cung cấp liên kết để tham khảo.
Arghya Sadhu
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.