Obj-C에서 Swift 's Enum을 사용할 수 있습니까?


145

Obj-C 클래스 중 일부를 Swift로 변환하려고합니다. 그리고 다른 일부 Obj-C 클래스는 여전히 변환 된 클래스에서 enum을 사용합니다. Pre-Release Docs에서 검색했는데 찾을 수 없거나 놓쳤을 수 있습니다. Obj-C Class에서 Swift enum을 사용하는 방법이 있습니까? 아니면이 문제의 문서에 대한 링크입니까?

이것이 내가 오래된 Obj-C 코드와 새로운 Swift 코드에서 열거 형을 선언 한 방법입니다.

내 오래된 Obj-C 코드 :

typedef NS_ENUM(NSInteger, SomeEnum)
{
    SomeEnumA,
    SomeEnumB,
    SomeEnumC
};

@interface SomeClass : NSObject

...

@end

나의 새로운 스위프트 코드 :

enum SomeEnum: NSInteger
{
    case A
    case B
    case C
};

class SomeClass: NSObject
{
    ...
}

업데이트 : 답변에서. 1.2 이전 버전의 Swift에서는 수행 할 수 없습니다. 그러나이 공식 스위프트 블로그 에 따르면 . XCode 6.3과 함께 릴리스 된 Swift 1.2에서는 Objective-C에서 Swift Enum @objc을 앞에 추가하여 사용할 수 있습니다.enum


기존 코드를 변경할 필요가 없습니다. Swift와 Objective-C 간의 상호 작용은 WWDC 비디오를보십시오.
gnasher729

미래에 내 프로젝트에 빠른 수업이 있는지 프로젝트가 여전히 작동하는지 확인하고 싶지만 테스트를 위해 어떤 수업을 추가해야하는지 파악할 수 없습니다. 그래서 나는 오래된 것을 대신 변환합니다. 어쨌든 도움을 주셔서 감사합니다.
myLifeasdog 2016 년

답변:


226

Swift 버전 1.2 (Xcode 6.3)부터 가능합니다. 단순히 열거 형 선언 앞에@objc

@objc enum Bear: Int {
    case Black, Grizzly, Polar
}

스위프트 블로그 에서 뻔뻔스럽게 찍은

참고 : String 열거 형 또는 관련 값이있는 열거 형에서는 작동하지 않습니다. 열거 형은 Int-bound해야합니다.


Objective-C에서 이것은 다음과 같습니다

Bear type = BearBlack;
switch (type) {
    case BearBlack:
    case BearGrizzly:
    case BearPolar:
       [self runLikeHell];
}

8
그것을 지적 ... 목표 - C에서 열거 값이 호출 될 것입니다하지만주의에 대한 감사를 많이 BearBlack, BearGrizzlyBearPolar!
nburk

1
말도 안돼? 특히 그것이 obj-c에서 swift로 어떻게 번역되는지를 볼 때 .. @nburk
Daniel Galasko

1
그렇습니다. 그러나 적어도 내 경우에는 프로젝트의 Objective-C 측에서 "@objc public enum Bear : Int"
Pirkka Esko

너무 나쁩니다 .Swift 열거 형 관련 값이 가능하다는 증거는 없습니다. 희망적인 생각
finneycanhelp

2
@AJit 왜 그렇게 하시겠습니까? 그냥 브리지 헤더에, 그렇지 않으면 스위프트 독점 있다는 자신의 헤더와 수입에 열거를 추가
다니엘 Galasko

31

선택한 답변을 확장하려면 ...

를 사용하여 Swift와 Objective-C간에 Swift 스타일 열거를 공유 할 수 있습니다 NS_ENUM().

그것들을 사용하여 Objective-C 컨텍스트에서 정의해야하며 NS_ENUM()Swift 도트 표기법을 사용하여 사용할 수 있습니다.

로부터 코코아와 사용 스위프트와 목표 - C

Swift는 NS_ENUM매크로 로 표시된 C 스타일 열거를 Swift 열거로 가져옵니다 . 즉, 열거 형 값 이름의 접두사는 시스템 프레임 워크 또는 사용자 정의 코드에 정의되어 있는지 여부에 관계없이 Swift로 가져올 때 잘립니다.

목표 -C

typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
   UITableViewCellStyleDefault,
   UITableViewCellStyleValue1,
   UITableViewCellStyleValue2,
   UITableViewCellStyleSubtitle
};

빠른

let cellStyle: UITableViewCellStyle = .Default

UITableViewCellStyle "함수 정의는 여기에서 허용되지 않습니다"라는 메시지가 표시됩니다. 물론 UITableViewCellStyle이 아닌 다른 이름이 있습니다.
Cristi Băluță

1
Galasko의 아래 답변에서 언급했듯이 Swift 1.2를 사용하면 열거 형을 Swift에서 정의하고 Obj-c에서 사용할 수 있습니다. 이 스타일의 정의, 즉 NS_ENUM은 여전히 ​​Obj-c에서 작동하지만 Swift 버전 1.2에서는 두 가지 옵션 중 하나를 사용할 수 있습니다.
SirNod

Swift의 ObjC 열거 형에 문제가 있음을 발견했습니다. if let a = MyEnum(rawValue: 12345)12345가 해당 열거의 일부가 아닌 것과 같은 조각 에서 결과는 선택 사항이 아니라 일부 유효하지 않은 열거입니다.
bio

30

로부터 코코아와 오브젝티브 -C와 사용 스위프트 가이드 :

Swift 클래스 또는 프로토콜은 @objc 속성으로 표시되어 Objective-C에서 액세스 가능하고 사용 가능해야합니다. [...]

Objective-C와 호환되는 한 @objc 속성으로 표시된 클래스 또는 프로토콜 내의 모든 항목에 액세스 할 수 있습니다. 여기에 나열된 것과 같은 Swift 전용 기능은 제외됩니다.

제네릭 튜플 / Swift에 정의 된 구조 / Swift에 정의 된 구조 / Swift에 정의 된 최상위 함수 / Swift에 정의 된 전역 변수 / Swift에 정의 된 Typealiases / Swift 스타일 가변형 / 중첩 유형 / Cureded 함수

따라서 Objective-C 클래스에서 Swift 열거 형을 사용할 수 없습니다.


2
해결 방법이 있습니까? Swift 클래스를 만들면 열거 형이 절대적으로 필요합니다. 해당 열거 형을 Objective-C에서도 사용할 수있게하려면 어떻게해야합니까?
Raul Lopez

4
@RaulLopezVillalpando Objective-C와 상호 운용 될 것이라는 것을 알고 있다면 Objective-C로 열거를 선언하고 두 언어가 공유하도록해야합니다.
Gregory Higley

3
"그래서 우리는 스위프트로의 전환을 돕기 위해이 다리를 만들었습니다. 그러나 Enums, Structs, Generics와 같은 멋진 것을 사용하고 싶을 때는 쓸모가 없습니다 ..."
Kevin R

22
이 답변은 더 이상 유효하지 않습니다! Xcode 6.3 / Swift 1.2부터 Swift 열거 형은 @objc@DanielGalasko가 아래 답변에서 지적한대로 objective-c 내에서 사용할 수도 있습니다 !
nburk

9
Swift 2.1 , " Int raw value type없이 Swift에 정의 된 계산" 으로 문서 의 현재 텍스트를 인용하여 위의 주석을 명확히하기 위해 . 따라서 Swift의 열거 형이 Int raw value 유형과 같이 선언 @obj enum MyEnum: Int되면 앞에서 언급 한 것처럼 Objective-C 파일에서 제대로 작동합니다. 당신의 열거가 같은 다른 원료 값 형식으로 선언하는 경우 @obj enum MyOtherEnum: String, 당신은 목표 - C 파일에서 사용할 수 없습니다
jjramos

7

스위프트 4.1, Xcode 9.4.1 :

1) Swift 열거 형은 접두사가 붙어 @objc있고 Int유형 이어야 합니다.

// in .swift file:
@objc enum CalendarPermission: Int {
    case authorized
    case denied
    case restricted
    case undetermined
}

2) Objective-C 이름은 열거 형 이름 + 대소 문자 이름입니다 (예 CalendarPermissionAuthorized:

// in .m file:
// point to something that returns the enum type (`CalendarPermission` here)
CalendarPermission calPermission = ...;

// use the enum values with their adjusted names
switch (calPermission) {
    case CalendarPermissionAuthorized:
    {
        // code here
        break;
    }
    case CalendarPermissionDenied:
    case CalendarPermissionRestricted:
    {
        // code here
        break;
    }
    case CalendarPermissionUndetermined:
    {
        // code here
        break;
    }
}

물론 Objective-C 파일의 가져 오기 목록에서 마지막 항목으로 Swift 브리징 헤더를 가져와야합니다.

#import "MyAppViewController.h"
#import "MyApp-Swift.h"

왜 MyApp-Swift가 마지막이어야합니까?
Paul T.

@PaulT. : 아마도 처리 순서와 관련이 있습니다. 다른 곳에 넣으면 작동하지 않을 것입니다.
leanne

나는 현재 프로젝트에서 거의 모든 파일에서 가져 오기 섹션의 끝 부분에 있지만 여러 파일에서 끝나지 않고 프로젝트가 작동하는지 확인했습니다. 새로운 Xcode에있을 수 있습니까? 현재 프로젝트를 컴파일하는 데 오랜 시간이 걸리기 때문에 지금 확인할 수는 없지만 나중에 확인하겠습니다.
Paul T.

2

ObjC 코드를 그대로 유지하려면 프로젝트에 도우미 헤더 파일을 추가하십시오.

Swift2Objc_Helper.h

헤더 파일에 다음 열거 형을 추가하십시오.

typedef NS_ENUM(NSInteger, SomeEnum4ObjC)
{
   SomeEnumA,
   SomeEnumB
};

숨겨진 헤더 파일을 포함하기 위해 .m 파일에 다른 위치가 변경 될 수 있습니다.

#import "[YourProjectName]-Swift.h"

[YourProjectName]을 프로젝트 이름으로 바꿉니다. 이 헤더 파일은 모든 Swift에서 정의 된 @objc 클래스를 ObjC에 열거합니다.

열거 형에서 암시 적 변환에 대한 경고 메시지가 표시 될 수 있습니다. 괜찮습니다.

그건 그렇고,이 헤더 도우미 파일을 사용하여 #define 상수와 같은 일부 ObjC 코드를 유지할 수 있습니다.


0

(나처럼) 실제로 String 열거 형을 사용하려는 경우 objective-c에 대한 특수 인터페이스를 만들 수 있습니다. 예를 들면 다음과 같습니다.

enum Icon: String {
    case HelpIcon
    case StarIcon
    ...
}

// Make use of string enum when available:
public func addIcon(icon: Icon) {
    ...
}

// Fall back on strings when string enum not available (objective-c):
public func addIcon(iconName:String) {
    addIcon(Icon(rawValue: iconName))
}

물론 이것은 자동 완성의 편의성을 제공하지 않습니다 (objective-c 환경에서 추가 상수를 정의하지 않는 한).


0

이것은 조금 더 도움이 될 수 있습니다

문제 설명 :-나는 스위프트 클래스에 열거 형을 가지고 있는데, 나는 다른 스위프트 클래스에서 액세스하고 있으며 이제 목표 C 클래스 중 하나에서 액세스해야합니다.

objective-c 클래스에서 액세스하기 전에 :-

enum NTCType   {
    case RETRYNOW
    case RETRYAFTER
}
 var viewType: NTCType? 

객관적인 c 클래스에서 액세스하기위한 변경 사항

@objc  enum NTCType :Int  {
    case RETRYNOW
    case RETRYAFTER
}

값에 전달하는 함수를 추가하십시오.

  @objc  func setNtc(view:NTCType)  {
        self.viewType = view; // assign value to the variable
    }

0

이것을 연구 한 후에 부분 답변 만 계속 찾았으므로 Objective C 코드에 사용되는 Swift 열거 형과 Swift 코드에 사용되는 Objective C 열거 형이있는 Objective C에 브리지 된 Swift 앱의 전체 예제를 만들었습니다. 실행하고 실험 할 수있는 간단한 Xcode 프로젝트입니다. Swift 5.0과 함께 Xcode 10.3을 사용하여 작성되었습니다.

프로젝트 예


프로젝트는 또한 목적 C. 신속한 열거의 정의에서 빠른 열거를 사용하여 어디는 표시되지 않습니다 enum SwAnimal선두 부족@obj
oliolioli을

0

다음과 같은 열거 형을 관찰하려고하는 경우 :

enum EnumName: String {
    case one = "One"
    case two = "Two"
}

이 해결 방법이 도움이되었습니다.

관찰 가능한 클래스 :

  • 창조하다 @objc dynamic var observable: String?
  • 다음과 같이 열거 형 인스턴스를 만듭니다.

    private var _enumName: EnumName? {
        didSet {
            observable = _enumName!.rawValue
        }
    }

관찰자 클래스 :

  • 창조하다 private var _enumName: EnumName?
  • 창조하다 private let _instance = ObservableClass()
  • 창조하다

    private var _enumObserver: NSKeyValueObservation = _instance.observe(\.observable, options: .new, changeHandler: { [weak self] (_, value) in
        guard let newValue = value.newValue else { return }
        self?._enumName = EnumName(rawValue: period)!
    })

그것보다 이제 _enumName관찰 가능 클래스에서 를 변경할 때마다 관찰자 클래스의 해당 인스턴스도 즉시 업데이트됩니다.

이것은 물론 지나치게 단순화 된 구현이지만 KVO 비 호환 속성을 관찰하는 방법에 대한 아이디어를 제공해야합니다.

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