[swift] 컴파일러 오류 : Objective-C 선택기가있는 메소드가 동일한 Objective-C 선택기가있는 이전 선언과 충돌합니다.

Swift를 배우기 시작했고 YouTube에서 훌륭한 Stanford University 비디오 강의를 따르고 있습니다. 관심이 있거나 도움이되는 링크는 다음과 같습니다 (내 문제를 이해할 필요는 없지만).

Swift로 iOS 8 앱 개발-2. 더 많은 Xcode 및 Swift, MVC

강의를 따르는 동안 내 코드가 비디오의 코드와 동일하지만 시스템에서 컴파일러 오류가 발생하는 지점에 도달했습니다. 많은 시행 착오 끝에 코드를 두 가지 예로 축소했습니다. 하나는 오류를 생성하거나 다른 하나는 오류를 발생시키지 않지만 실제로 오류의 원인 또는 오류를 해결하는 방법을 모릅니다.

오류를 생성하는 코드는 다음과 같습니다.

import UIKit

class BugViewController: UIViewController
{
    func perform(operation: (Double) -> Double) {
    }

    func perform(operation: (Double, Double) -> Double) {
    }
}

다음과 같은 컴파일러 오류가 발생합니다.

Objective-C 선택기와 함께 ‘perform’메소드 ‘perform :’은 동일한 Objective-C 선택기로 이전 선언과 충돌합니다.

UIViewController의 하위 클래스를 제거하면 코드가 다음과 같이 컴파일됩니다.

import UIKit

class BugViewController
{
    func perform(operation: (Double) -> Double) {
    }

    func perform(operation: (Double, Double) -> Double) {
    }
}

관련이 있거나 관련이없는 기타 정보 :

  • 최근에 요세미티로 업그레이드했습니다.
  • Xcode를 설치할 때 베타 버전 (버전 6.3 (6D543q))으로 끝났습니다 (정확하게 기억한다면) 이것이 OS X 버전에서 실행하는 데 필요한 버전이기 때문입니다.

그렇지 않으면 이것이 나에게 의미가 없기 때문에 컴파일러의 버그라고 생각합니다. 어떤 도움도 대단히 감사합니다!



답변

Objective-C는 메소드 오버로드를 지원하지 않으므로 다른 메소드 이름을 사용해야합니다. UIViewController를 상속하면 NSObject를 상속하고 클래스를 Obj-C와 상호 운용 가능하게 만들었습니다. 반면에 스위프트는 오버로드를 지원하므로 상속을 제거 할 때 작동합니다.


답변

나 자신도 Standford 과정을 수강하고 있으며 오랫동안 여기에 붙어 있지만 검색 한 후에 Xcode 릴리스 노트 와 아래 에서 뭔가를 발견 했습니다.

Swift 1.2는 Objective-C에서 지원하지 않는 @objc 메소드 및 이니셜 라이저의 유형 기반 과부하를 검사하는 데 엄격합니다.

// Has the Objective-C selector "performOperation:".
func performOperation(op: NSOperation) { /* do something */ }
// Also has the selector "performOperation:".
func performOperation(fn: () -> Void) {
    self.performOperation(NSBlockOperation(block: fn))
}

이 코드는 Swift에서 호출 될 때 작동하지만 Objective-C에서 호출되면 쉽게 충돌 할 수 있습니다. 이 문제를 해결하려면 Objective-C에서 지원하지 않는 유형을 사용하여 Swift 컴파일러가 멤버를 Objective-C 런타임에 노출하지 못하게하십시오.

  • 의미가 있다면 @objc의 추론을 비활성화하기 위해 멤버를 private으로 표시하십시오.
  • 그렇지 않으면 기본값으로 더미 매개 변수를 사용하십시오 (예 : _ nonobjc : () = ()). (19826275)

프라이빗 서브 클래스에서 Objective-C에 노출 된 메소드의 대체는 @objc로 유추되지 않으므로 Swift 컴파일러가 중단됩니다. 이러한 대체 메소드에 @objc 속성을 명시 적으로 추가하십시오. (19935352)

Swift를 사용하는 프로젝트 또는 작업 공간에서 빨리 열기를 사용할 때는 SDK의 기호를 사용할 수 없습니다. (20349540)

내가 한 것은 다음과 같이 재정의 방법 앞에 “비공개”를 추가하는 것입니다.

    private func performOperation(operation: Double -> Double) {
    if operandStack.count >= 1 {
        displayValue = operation(operandStack.removeLast())
        enter()
    }
}


답변

이미 대답했듯이 ObjC는 메소드 오버로드 (동일한 이름을 가진 두 가지 메소드)를 지원하지 않으며 Xcode 7의 swift 2에는 이러한 종류의 문제를 해결할 수있는 두 가지 옵션이 있습니다. 한 가지 옵션은 속성을 사용하여 메소드의 이름을 바꾸는 것입니다.@objc(newNameMethod:)

func methodOne(par1, par2) {...}

@objc(methodTwo:)
func methodOne(par1) {...}

Xcode 7+에서이 문제를 해결하는 또 다른 옵션은 @nonobjc모든 메소드, 첨자 또는 이니셜 라이저에 속성을 적용하는 것입니다.

func methodOne() {...}

@nonobjc
func methodOne() {...}


답변

하는 문제는 UIViewController입니다 @objc클래스입니다. 상속 할 때 UIViewController, BugViewController또한입니다 @objc클래스입니다.

이는 Objective-C 선택기의 규칙 (메소드 이름)을 준수해야 함을 의미합니다. 메소드 func perform(operation: (Double) -> Double)func perform(operation: (Double, Double) -> Double)둘 다 동일한 선택기를가 @selector(perform:)집니다. 이것은 허용되지 않습니다.

이 문제를 해결하려면 like func perform1(operation: (Double) -> Double)및 다른 이름을 사용하십시오 func perform2(operation: (Double, Double) -> Double).


나는 이것을 처리하는 가장 좋은 방법은 당신의 perform()방법에 더 설명적인 이름 을 부여하는 것이라고 생각합니다 . 이 방법들은 무엇을 하는가? 뷰 컨트롤러의 상태를 어떻게 변경합니까? UIViewController메소드 이름 지정 스타일에 대한 느낌을 얻으려면 다른 메소드를 보거나 클래스 내에서 표현적이고 고유해야하는 메소드 이름을 읽으 십시오.


답변

에서 https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html “엑스 코드 6.3 릴리스 노트”에서 것은 -> “스위프트 언어 변경”찾을

Swift는 이제 Swift 유형 시스템에서 오버로드와 재정의 사이의 불일치와 Objective-C 런타임을 통해 보이는 효과적인 동작을 감지합니다.


답변

동일한 Obj-C 서명으로 두 가지 방법을 사용했기 때문에 동일한 오류가 발생했습니다.

static func prepareForUpSyncing(obj : NSManagedObject!) -> Bool
static func prepareForUpSyncing(objs : [NSManagedObject]!) -> Bool

런타임에 예기치 않은 결과가 발생할 수 있기 때문에 그중 하나를 @nonobjc로 표시하고 싶지 않았습니다. (가능성이 없으면 누군가 나를 교정 할 수 있습니다)

Swift의 외부 매개 변수 이름 기능 (로컬 이름과 외부 이름을 동일하게 함)을 사용하여 Obj-c 메서드 서명을 효과적으로 변경하여이를 해결했습니다.

static func prepareForUpSyncing(objs objs : [NSManagedObject]!) -> Bool {


답변