Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

init an NSNumber from enum element in mixed-language project

I have a mixed-language project, Objective C and Swift, in XCode 6.

Singleton.h

#import <Foundation/Foundation.h>

enum  {
    enum_A = 0,
    enum_B,
    enum_C,
    enum_D,
    enum_E,
    enum_F,
    enum_G,
} enums;

@interface Singleton : NSObject

+ (id)sharedSingleton;

@end

Singleton.m

// Nothing's special in this file

#import "Singleton.h"

static Singleton *shared = nil;

@implementation Singleton

- (id)init {
    self = [super init];
    if (self) {

    }
    return self;
}

#pragma mark - Interface

+ (Singleton *)sharedSingleton {
    static dispatch_once_t pred;

    dispatch_once(&pred, ^{
        shared = [[Singleton alloc] init];
    });

    return shared;
}

@end

ViewController.swift

import UIKit

class ViewController: UIViewController {

let singleton = Singleton.sharedSingleton() as Singleton

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let n = NSNumber(char: enum_E) // ERROR HERE!!!
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

(Of course I had to setup bridging header file, having #import "Singleton.h" added).

The ERROR is:

Cannot invoke 'init' with an argument list of type '(char: Int)'

It's strange that Swift can still recognize enum_E (I see it colorized in blue) but still pops up this error. I tried (char)enum_E but still no luck.

Do you have any ideas?

Thanks,

like image 941
quanguyen Avatar asked Dec 12 '14 09:12

quanguyen


1 Answers

Okay, apparently there actually is a difference between enums created in Objective-C and Swift. I assumed there was no difference, thus I only tested my approach in a Swift Playground.


enum created in Swift
// UInt32 used to have the same underlying type in both examples
enum TestEnum : UInt32 { 
    case A, B, C
}

var x = NSNumber(unsignedInt: TestEnum.C.rawValue)
// x == 2

To get the raw value from an enum value in Swift, you have to explicitly transform the enum value into the raw value. This can be done by adding .rawValue to your enum value.


enum created in Objective-C

Objective-C

enum TestEnum {
    A = 0,
    B = 1,
    C = 2
};

Swift

let x : TestEnum = C
var number = NSNumber(unsignedInt: C.value) // alternative: x.value
println("the number is \(number)")
// Outputs: the number is 2

The difference to the Swift enums seems to be that you have to use .value instead of .rawValue and you can not prefix them with the type. The raw type in this case is UInt32.

Tested in Xcode 6.1.1, iOS SDK 8.1, iOS Simulator 8.1

like image 115
Nero Avatar answered Nov 09 '22 13:11

Nero