"치명적인 오류 : Objective-C에서 어레이를 연결할 수 없습니다."— 당신은 왜 시도하고 있습니까, Swift?


92

Swift 프로토콜을 선언했습니다.

protocol Option {
    var name: String { get }
}

이 프로토콜의 여러 구현 (일부 클래스, 일부 열거 형)을 선언합니다.

다음과 같이 선언 된 속성이있는 뷰 컨트롤러가 있습니다.

var options: [Option] = []

이 속성을 Option다른 VC에서 프로토콜 을 구현하는 개체 배열로 설정하려고 prepareForSegue하면 런타임 오류가 발생합니다.

fatal error: array cannot be bridged from Objective-C

왜 작동하지 않습니까? 컴파일러는 필요한 모든 정보를 가지고 있으며 Objective-C가 그것과 어떤 관련이 있는지 전혀 이해하지 못합니다. 내 프로젝트에는 Swift 파일 만 포함되어 있으며 이러한 배열은 어떤 프레임 워크 메소드에서도 들어 오거나 나오지 않습니다. 에 브리지되어야 NSArray합니다.


6
@objc프로토콜 앞에 추가하려고 했습니까 ? stackoverflow.com/a/28029568/377369
Fabio Poloni

1
프로토콜 구현이 열거 형이면 작동하지 않습니다. "비 클래스 유형 'Foo'는 클래스 프로토콜 '옵션'을 준수 할 수 없습니다."
Robert Atkins

그래도 클래스 프로토콜이어야하는 이유는 무엇입니까? Obj-C 프레임 워크 또는 NSArray에 브리지되어야하는 Swift Array를 필요로하는 다른 것에 전달하지 않습니다.
Robert Atkins 2015 년

Swift와 Objective-C가 함께 작동하는 방식은 여전히 ​​나에게 비밀입니다. 나는 단지 "작동"하거나 "작동하지 않는"많은 것들을 "수락"해야한다.
Fabio Poloni

9
왜 이렇게 많은 반대표가 있습니까? 공정하고 명확한 질문처럼 보입니다.
Guven

답변:


83

해결책을 찾았습니다. 상당히 ... 불만족 스럽지만 작동합니다. 대상 뷰 컨트롤러에서 배열을 설정하는 곳 :

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

전체 배열을 캐스트 할 수 없습니까? options as [Option]
Kostiantyn Koval

아니. 시도 (Xcode 6.3.1 (6D1002)), 작동하지 않습니다. 어떤 경우에도 캐스팅 할 필요 가 없습니다 . 컴파일러는 내가 Option을 구현하는 배열을 전달하고 있음을 알고 있습니다.
Robert Atkins

2
"옵션을 구현하는 것들의 배열"아,하지만 그것은 당신이 필요로하는 옵션의 배열과는 다릅니다. 내 대답을 참조하십시오.
Matt

1
이것은 효과가 있고, 예, 매우 불만족 스럽습니다 ... 이것은 필요하지 않습니다. Swift는 htis를 처리 할 수 ​​있어야합니다.
오스카 고메즈

동의합니다 ...이 방식으로 작동하지만 매우 불만족스러운 코드입니다
Michael

22

컴파일러는 내가 Option을 구현하는 배열을 전달하고 있음을 알고 있습니다.

당신은 문제의 원인을 암시하는 매우 드러나는 발언을 놔 두었습니다. "옵션을 구현하는 사물의 배열"은 옵션의 배열이 아닙니다.

문제는 options백을 생성 한 시점 (에서 prepareForSegue) 의 백 유형에 있습니다 . 당신은 그 코드를 보여주지 않았지만, 나는 당신이 그 시점에서 그것을 캐스팅 / 타이핑하지 못했을 것이라고 확신합니다. 이것이 할당이 실패하는 이유입니다.options실제로 Option을 채택하기 위해 발생하는 일들의 배열 일 수 있지만 그것만으로는 충분하지 않습니다. Option의 배열 로 입력 해야합니다 .

따라서 다시에서 prepareForSegue다음 options과 같이 형성하십시오 .

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

지금 직접 할당 할 수 있습니다 destinationViewController.options.

다음은 빠른 테스트 사례입니다 (놀이터에서, 나는 놀이터를 싫어하지만 용도가있을 수 있습니다).

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

(실제로 실제 앱에서 이것을 테스트 prepareForSegue했으며 제대로 작동합니다.)


1
컴파일러 런타임에 Thing이 옵션이라는 것을 알고 있기 때문에 이것이 극단적으로 손상되었다고 생각합니다 . 그리고 어쨌든 아래 내 답변에 대한 주석에서 언급했듯이 캐스팅 ( viewController.options = things as [Option])도 [Option]여기에서 제안한대로 명시 적으로 입력 된 임시 변수를 만드는 것도 실제로 작동하지 않습니다. 두 경우 모두 런타임 오류가 발생합니다.
Robert Atkins

그런 다음 왜 그것이 저에게 효과가 있는지 설명해야합니다. 당신이 말하지 않은 다른 일이 일어나고 있습니다. 더 많은 코드를 공개하지 않으면 중요한 것을 보류하고 있다고 의심해야합니다.
매트

아마도. 그러나 나는 이것이 처음에 Objective-C와 관련이 있는지에 대해 여전히 혼란 스럽습니다 (원래 런타임 오류). 나는 브리징 캐스트를 강제 해야하는 (볼 수있는) 아무것도하지 않고 있습니다. NSArray.
Robert Atkins

2
이쪽으로 봐. 작동하는 코드를 보여 드렸습니다. 당신은 하지 나 코드를 표시 하지 않습니다 내가 주어진 데이터에서 문제를 재현 할 수 없습니다 - 일을. 재현하도록 도와주세요.
매트

1
@ CristiBăluță "이 문제는 아직 해결되지 않았습니다"라고 주장하기 전에 알아 내야 할 사항입니다
matt

16

나는 같은 문제가 있었고 내 프로토콜을으로 표시하여 수정했습니다 @objc. 귀하의 경우에는 다음과 같이 보일 것입니다.

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

이 답변 에서 해결책을 얻었습니다.


1
원래 질문에 대한 의견에서와 같이 프로토콜의 구현자가 Swift Enum 인 경우 작동하지 않습니다. 제 경우에는 그렇습니다.
Robert Atkins

오타 obcj는 objc해야한다
앨런 스카 르파

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.