ARC forbids Objective-C objects in structs or unions

問題

SwiftとObjective-Cが混在しているプロジェクトファイルの ***-Bridging-Header.h でとあるObjective-Cのヘッダーファイルをインクルードしたら、

ARC forbids Objective-C objects in structs or unions

エラーが出た。

コード

TestProj-Bridging-Header.h

#import "Test.h"

Test.h
エラーがでたのは、ここの4行目

// 構造体の定義
typedef struct{
    int num;
    NSString* name;
} Info;

// 構造体を使用するクラス
@interface TestClass : NSObject

- (void) Piyo;

@end

Test.m

#import "Test.h"

@implementation TestClass

@property Info info;

- (void) Piyo {
    int i = 0;
}
@end

Main.swift

let test = TestClass()
test.Piyo()

原因

構造体の中に、NSObjectを継承した型があるとダメだよということらしい。

ARCでstructの中にObjective-Cインスタンスを入れると出るエラーの回避方法 | dendrocopos開発室
ARC有効時はC言語の構造体にObjective-Cオブジェクトは使えない
もう、新しいプロジェクトではAuto Reference Counting(ARC)を当たり前のように使ってい…

解決策

仕方ないので、該当する構造体を利用した関数を呼び出す用のラッパークラスをObjective-Cで作成し、
その関数を経由して呼び出すようにした。

コード

TestProj-Bridging-Header.h

#import "NewTest.h"

Test.h / Test.m はそのまま

NewTest.h

@interface NewTestClass : NSObject

+ (void) Piyo;

@end

NewTest.mm
※ ファイルの拡張子を .mm にする。
そうすることで、Objective-C++としてビルドされ、問題が回避できる。

#import "Test.h"

@implementation NewTestClass

+ (void) Piyo {
    TestClass* test = [[TestClass alloc] init];
    [test Piyo];
}

@end

Main.swift

let test = NewTestClass()
test.Piyo()

ボツ案

  • 構造体をクラスに置き換える
    • この構造体は他のクラスでも使用されているため、置き換えるのは非現実的
  • 構造体の中のNSObjectを継承した型のみ、C言語の型に置き換える
    • ちょっと試してみたけどあまり賢くない