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?
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?
Câu trả lời:
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.h
tệp rõ ràng vào Tệp Mục tiêu-C cũ hơn.)
Thêm một .m
tập tin vào lớp của bạn và đặt tên cho nó CustomObject.m
.
Khi thêm .m
tệ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:
Nhấp vào Có !
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 .h
tệ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 .h
tệ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:
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
Thêm một .h
tập tin khác và đặt tên cho nó CustomObject.h
.
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
Trong YourProject-Bridging-Header.h
:
#import "CustomObject.h"
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.
Thêm một .swift
tậ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)"
}
}
Trong SomeRandomClass.m
:
#import "<#YourProjectName#>-Swift.h"
Tệp: <#YourProjectName#>-Swift.h
nê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ó.
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);
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.
Nếu bạn thêm một .swift
tệ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 .
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 @objc
tiề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 @objc
bằ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 @objc
mà không có những hạn chế này.
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 8 và OS 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
).
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:
Trong các bước đơn giản:
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.
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.
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"
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ã".
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 .
Tôi đã viết một dự án Xcode 6 đơn giản chỉ ra cách trộn mã C ++, Objective-C và Swift:
https://github.com/romitagl/spl/tree/master/C-ObjC-Swift/Performance_Console
Cụ thể, ví dụ này gọi hàm Objective-C và C ++ từ Swift .
Chìa khóa là tạo một tiêu đề được chia sẻ, Project-Bridging-Header.h và đặt các tiêu đề Objective-C ở đó.
Vui lòng tải về dự án như một ví dụ hoàn chỉnh.
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 cocoapods
thư 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 import
các lớp vào Swift.
Điều đơn giản bạn phải làm là:
<YOUR-PROJECT>-Bridging-Header
tập tin và#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 import
khi #import
không hoạt động.
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.
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 .
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"
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ã".
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
?
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
.
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 objc
và 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.h
vào ô đó để tạo đường dẫn tệp.
Bước_08: Mở Objc-Bridging-Header.h
tệ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)
}
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.
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
}
}
Thêm tiêu đề .h
và .m
tệp thực hiện - Tệp lớp ca cao (Objective-C)
Ví dụMyFileName
cấu hình tiêu đề bắc cầu
Khi bạn thấy Would you like to configure an Objective-C bridging header
nhấp - Có
<target_name>-Bridging-Header.h
sẽ được tạo tự độngThêm Class để Bridging-Header
Trong <target_name>-Bridging-Header.h
thê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.h
trước
Thêm một <MyFileName>.swift
và mở rộngNSObject
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
Đánh dấu mã Swift công khai [@objc và @objcMembers]
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:
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.
Cách tiếp cận hai cách để sử dụng object-c object-c
1
2
Bây giờ tốt để đi Cảm ơn