“Lỗi nghiêm trọng: không thể bắc cầu mảng từ Objective-C” —Tại sao bạn lại cố gắng, Swift?


92

Tôi đã khai báo một giao thức Swift:

protocol Option {
    var name: String { get }
}

Tôi khai báo nhiều triển khai của giao thức này — một số lớp, một số enum.

Tôi có bộ điều khiển chế độ xem với thuộc tính được khai báo như vậy:

var options: [Option] = []

Khi tôi thử và đặt thuộc tính này thành một mảng đối tượng triển khai Optiongiao thức trong VC khác prepareForSegue, tôi gặp lỗi thời gian chạy:

fatal error: array cannot be bridged from Objective-C

Tại sao điều này không hoạt động? Trình biên dịch có tất cả thông tin nó cần và tôi không hiểu Objective-C phải làm gì với nó — dự án của tôi chỉ chứa các tệp Swift và các mảng này không đến hoặc ra khỏi bất kỳ phương thức khung nào. yêu cầu họ phải được bắc cầu NSArray.


6
Bạn đã thử thêm trước vào @objcgiao thức của mình chưa? stackoverflow.com/a/28029568/377369
Fabio Poloni

1
Điều đó không hoạt động nếu bất kỳ triển khai giao thức nào là một enum: "Loại không phải lớp 'Foo' không thể phù hợp với giao thức lớp 'Tùy chọn'"
Robert Atkins

Tại sao nó phải là một giao thức lớp? Tôi không chuyển nó sang khung Obj-C hoặc bất kỳ thứ gì khác yêu cầu Mảng Swift được bắc cầu với NSArray.
Robert Atkins

Cách Swift và Objective-C làm việc cùng nhau vẫn là một bí mật đối với tôi. Tôi chỉ phải "chấp nhận" nhiều thứ mà chỉ "hoạt động" hoặc "không hoạt động".
Fabio Poloni

9
Tại sao cái này lại có nhiều phiếu phản đối? Có vẻ như một câu hỏi công bằng và rõ ràng đối với tôi.
Guven

Câu trả lời:


83

Tôi đã tìm ra một giải pháp. Nó khá là ... không hài lòng , nhưng nó hoạt động. Nơi tôi đặt mảng trên bộ điều khiển chế độ xem đích, tôi thực hiện:

destinationViewController.options = options.map({$0 as Option})

bạn không thể ép toàn bộ mảng? options as [Option]
Kostiantyn Koval

Không. Đã thử nó (Xcode 6.3.1 (6D1002)), không hoạt động. Tôi không cần phải truyền nó trong bất kỳ trường hợp nào, trình biên dịch biết tôi đang truyền vào Mảng những thứ triển khai Option.
Robert Atkins

2
"một Mảng những thứ thực hiện Tùy chọn" À, nhưng điều đó không giống với Mảng tùy chọn, đó là thứ bạn cần. Hãy xem câu trả lời của tôi.
matt

1
Điều này hoạt động, và vâng nó rất không hài lòng ... điều này không cần thiết. Swift sẽ có thể xử lý htis.
Oscar Gomez

Tôi tán ... nó hoạt động theo cách này, nhưng nó là một chút rất không hài lòng của mã
Michael

22

trình biên dịch biết tôi đang chuyển một Mảng những thứ thực hiện Option

Bạn đã để lọt vào đó một nhận xét rất tiết lộ, gợi ý nguồn gốc của vấn đề. Một "Mảng những thứ thực hiện Tùy chọn" không phải là Mảng Tùy chọn.

Vấn đề là với loại optionsmặt sau tại điểm bạn tạo nó (trong prepareForSegue). Bạn không hiển thị mã đó, nhưng tôi cá rằng bạn không thể nhập / nhập mã tại thời điểm đó. Đó là lý do tại sao nhiệm vụ không thành công. optionscó thể là một loạt những thứ xảy ra trên thực tế khi áp dụng Quyền chọn, nhưng điều đó là chưa đủ; nó phải được nhập dưới dạng một mảng Tùy chọn.

Vì vậy, quay trở lại prepareForSegue, tạo thành optionsnhư sau:

let options : [Option] = // ... whatever ...

Bây giờ bạn sẽ có thể chỉ định nó trực tiếp cho destinationViewController.options.

Đây là một trường hợp thử nghiệm nhanh (trong một sân chơi; tôi ghét các sân chơi, nhưng chúng có thể có công dụng của chúng):

protocol Option {
    var name : String {get}
}

class ViewController : UIViewController {
    var options : [Option] = []
}

enum Thing : Option {
    var name : String {
        get {
            return "hi"
        }
    }
    case Thing
}

let vc = ViewController()
let options : [Option] = [Thing.Thing]
vc.options = options // no problem

(Tôi cũng đã thử nghiệm điều này trong một ứng dụng thực tế với một ứng dụng thực tế prepareForSeguevà nó hoạt động tốt.)


1
Tôi nghĩ rằng điều này bị phá vỡ ở mức cực đoan bởi vì trình biên dịch không biết trong thời gian chạy rằng Điều đó là một Tùy chọn. Và trong mọi trường hợp, như đã lưu ý trong nhận xét cho câu trả lời của riêng tôi bên dưới, không ép kiểu ( viewController.options = things as [Option]) hay tạo biến tạm thời được nhập rõ ràng [Option]như bạn đề xuất ở đây, thực sự hoạt động. Trong cả hai trường hợp, tôi gặp lỗi thời gian chạy.
Robert Atkins

Sau đó, bạn phải giải thích tại sao nó hoạt động cho tôi. Có điều gì khác đang xảy ra mà bạn chưa nói rõ. Nếu bạn không tiết lộ thêm mã, tôi chỉ đơn giản là phải nghi ngờ rằng bạn đang giữ lại một cái gì đó thiết yếu.
matt

Có lẽ. Nhưng tôi vẫn bối rối không biết điều này phải làm gì với Objective-C ngay từ đầu (với lỗi thời gian chạy ban đầu). NSArray.
Robert Atkins

2
Nhìn nó theo cách này. Tôi đã chỉ cho bạn mã hoạt động. Bạn đã không hiển thị cho tôi mã không hoạt động - Tôi không thể tái tạo sự cố của bạn từ dữ liệu đã cho. Giúp tôi tái tạo nó.
matt

1
@ CristiBăluță Đó là những gì bạn cần tìm hiểu trước khi tuyên bố "sự cố này vẫn chưa được khắc phục"
matt

16

Tôi đang gặp phải vấn đề tương tự và đã sửa nó đánh dấu giao thức của tôi với @objc, trong trường hợp của bạn, nó sẽ giống như thế này

@objc protocol Option {
    var name: String { get }
}

Có giải pháp từ câu trả lời này


1
Như trong các nhận xét về câu hỏi ban đầu, điều này không hoạt động nếu bất kỳ người triển khai giao thức nào là Swift Enums. Mà trong trường hợp của tôi là họ.
Robert Atkins

typo obcj nên là objc
Alan Scarpa

1

Cái này cũng hoạt động tốt

destinationViewController.options = options.map{$0}
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.