Mã mục tiêu-c có thể gọi tiện ích mở rộng nhanh trên Lớp không?


94

Tôi đã tìm kiếm một số bài đăng, tôi nghĩ rằng tôi không thể viết tiện ích mở rộng nhanh chóng và gọi nó từ mã Objective-C, phải không?

@objc như các thuộc tính chỉ hỗ trợ phương thức, lớp, giao thức?


1
Tại sao bạn không thử một lần?
ĐÃ

7
Ý kiến ​​bị lỗi, nhưng tôi muốn có được một nhà cảm xạ xác định.
sprhawk

Câu trả lời:


84

Bạn có thể viết một phần mở rộng Swift và sử dụng nó trong mã Objective-C. Đã kiểm tra với XCode 6.1.1.

Tất cả những gì bạn cần làm là:

  • tạo tiện ích mở rộng của bạn bằng Swift (không có @objcchú thích)

  • #import "ProjectTarget-Swift.h" trong lớp Objective-C của bạn (trong đó "ProjectTarget" đại diện cho mục tiêu XCode mà tiện ích mở rộng Swift được liên kết với)

  • gọi các phương thức từ phần mở rộng Swift

Cập nhật: Kể từ khi @Rizwan Ahmed được đề cập, bạn cần thêm @objcchú thích:

Kể từ Swift 4.0.3, chú thích @objc là cần thiết nếu bạn muốn sử dụng tiện ích mở rộng trong các tệp lớp Objective C.


6
Tôi đã thực hiện chính xác điều này nhưng nó vẫn là lỗi thời gian biên dịch. Hừ! CHỈNH SỬA: Tôi đã nhập tiêu đề bắc cầu của mình, thay vì "ProjectTarget-Swift.h". Der.
Jason Renaldo

Cả hai đều là tiêu đề bắc cầu. Sự khác biệt là một cái dùng để sử dụng mã Swift trong ObjC và cái còn lại để sử dụng mã ObjC trong Swift. Tiêu đề Swift là ẩn. Cái còn lại, sẽ do bạn quản lý.
marius bardan

William Hu, hãy xem câu trả lời của mclaughlinj!
appleitung

39
Kể từ Swift 4.0.3, chú thích @objc là cần thiết nếu bạn muốn sử dụng tiện ích mở rộng trong các tệp lớp Objective C.
Rizwan Ahmed

68

Tôi phát hiện ra rằng trong Swift 4.0, tôi phải thêm @objcvào trước từ khóa tiện ích mở rộng của mình để các phương thức mở rộng Swift hiển thị bởi một phiên bản của lớp objc mà tôi đang mở rộng.

Nói ngắn gọn:

Thiết lập cấu hình tệp:

CustomClass.h
CustomClass.m
CustomClassExtension.swift

Trong CustomClassExtension:

@objc extension CustomClass
{
    func method1() 
    {
        ...
    }
}

Trong AppDelegate.m của tôi:

self.customClass = [[CustomClass alloc] init];
[self.customClass method1];

2
Nếu một phương pháp sử dụng generic, Objective-C không thể sử dụng nó và bạn sẽ cần thêm @nonobjcchú thích.
ThomasW

Chỉ là một chú thích phụ, @objcMembers không hoạt động trong trường hợp này. Không biết tại sao .. :-(
Raunak

46

Giải pháp này hoạt động cho Swift 2.2 và Swift 3 . Lưu ý rằng chỉ các phần mở rộng cho các lớp (không phải cho cấu trúc hoặc enum) mới có thể truy cập được từ 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)
    }
}

Sau đó, #import "ProductModuleName-Swift.h" trong tệp ObjC của bạn.

Swift 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)
    }
}

Nó không phải là "YourProjectsNameHere ..." mà là "YourTargetsNameHere ...": để chia sẻ mục tiêu, bạn phải khóa nó thành tên: dr2050.postach.io/post/…
Dan Rosenstark

1
@DanRosenstark Bạn nói đúng. Tôi đang thay đổi nó thành "ProductModuleName-Swift.h" như Apple đề xuất: developer.apple.com/library/ios/documentation/Swift/Conceptual/…
Foti Dim

1
Hoạt động tốt cho nhanh chóng 3.
Viktor Kucera

Có một lý do tại sao bạn nói publiclà cần thiết? Hoạt động tốt mà không cần publicsửa đổi cho tôi. Chúng ta có giả định rằng phần mở rộng không nằm trong cùng một dự án mà được nhập từ một dự án khác không?
Lee Kang

Tôi có cần sử dụng tiêu đề bắc cầu không?
jegadeesh

42

Như đã đề cập trong các câu trả lời khác, việc nhập tiêu đề Swift đã tạo hoạt động trong hầu hết các trường hợp .

Một ngoại lệ cho điều này là khi danh mục được xác định trên một kiểu bắc cầu (nghĩa là phần mở rộng được xác định trên Stringvà không NSString). Các danh mục này sẽ không tự động được bắc cầu với các đối tác Objective-C của chúng. Để giải quyết vấn đề này, bạn sẽ cần sử dụng kiểu Objective-C (và truyền giá trị trả về trong mã Swift của bạn với as String) hoặc xác định phần mở rộng cho cả kiểu Swift và Objective-C.


2
Thêm vào câu trả lời ở trên, bạn nên thực hiện mở rộng công nhanh chóng của bạn và đặt loại của nó như NSString ví dụ public extension NSString. Bạn sẽ nhận được một định danh chưa được giải quyết hoặc báo lỗi tương tự tại thời gian biên dịch, bạn có thể cast một lần nữa trở lại với chuỗi ví dụ let sVal = self as Stringvà sau đó gọi mã cần thiết trênsVal
runloop

@RunLoop thực ra bạn không cần public, nó sẽ hoạt động mà không cần chỉ định phạm vi. Và nó (ý tôi là xuất sang Obj-C) không hoạt động cho Chuỗi, vì chúng là cấu trúc, không phải lớp và chỉ có sẵn từ Swift. Vì vậy, có - bạn có thể viết phần mở rộng cho NSString và sử dụng dàn diễn viên, hoặc mở rộng ghi, như mclaughlinjđã nói, cho cả lớp NSString và String struct
Alex Nazarsky

3

Nhập "#import 'ProductModuleName-Swift.h' tiêu đề trong tệp Objective-C và thêm @objc trước mặt bạn extentsion trong tập tin nhanh chóng. Nó sẽ làm việc tốt trong nhanh chóng 4.2 và nhanh chóng 5

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.