【iOS】Xcodeでビルドした時にNSObjCRuntimeでエラー？【cocos2d-x】

# また謎のエラー…
Xcodeでビルドした時に謎のエラーが出る事があります。
**「え、チェックアウトしただけで、特に何もコード変えてないのに何でエラー！？」**
なんて事もあります。
もちろんエラーは状況により様々ですが、その中でもcocos2d-xを使っていると
出会うかもしれないエラーとその解決法をご紹介します。

# サンプルを作成
全体のコードはgithubにUP致しました。→[コチラ](https://github.com/jake1256/Cocos2dxNSObjCRuntimeErrorTest)

今回はエラーを発生させる可能性がある、iOS , aOSで処理を切り分ける必要があるプログラムをcocos2d-xで用意しました。
なお、使用したcocos2d-xのVersionは3.3rc0です。

```cpp:NativeUtil.h
//  NativeUtil.h
#ifndef __Cocos2dxNSObjCRuntimeErrorTest__NativeUtil__
#define __Cocos2dxNSObjCRuntimeErrorTest__NativeUtil__

#include <stdio.h>

class NativeUtil
{
public:
    static void showWebBrowser(std::string url);
};

#endif /* defined(__Cocos2dxNSObjCRuntimeErrorTest__NativeUtil__) */
```

```cpp:NativeUtil.cpp
//  NativeUtil.cpp
#include "NativeUtil.h"


#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#import <objc/runtime.h>
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#endif

/**
 * URLを指定して端末ブラウザと連携する
 */
void NativeUtil::showWebBrowser(std::string url)
{
    NSString *urlString = [NSString stringWithFormat:@"%s" , url.c_str()];
    NSURL *nsUrl = [NSURL URLWithString:urlString];
    
    // ブラウザを起動する
    [[UIApplication sharedApplication] openURL:nsUrl];
}
```

# 動作確認
こんな感じです。
あくまでサンプルなので、サラッと読み飛ばしてください。

真ん中のボタンを押下すると端末ブラウザと連携します。
![iOS Simulator Screen Shot 2014.10.26 18.51.31.png](https://qiita-image-store.s3.amazonaws.com/0/26453/d9fb1830-385c-1ec4-41b2-6145a5f8a06c.png)



この例では[cocos2d-x](http://www.cocos2d-x.org/)のウェブサイトに遷移させました。
![iOS Simulator Screen Shot 2014.10.26 18.51.37.png](https://qiita-image-store.s3.amazonaws.com/0/26453/c071e82d-6fea-f1bf-0c86-7e84482267b7.png)



# え？NSObjCRuntimeエラー！？
エラーを発生させました。こんなエラーです。
![スクリーンショット 2014-10-26 18.52.33.png](https://qiita-image-store.s3.amazonaws.com/0/26453/9f1f43d4-5c2f-ff49-5f8d-53a03c37e9a9.png)

こういうエラーは特に見たくないですね。

# 原因
これが原因です。
![スクリーンショット 2014-10-26 19.14.18.png](https://qiita-image-store.s3.amazonaws.com/0/26453/e401503c-8c38-1d7a-68b6-b0ed16fa0d94.png)

この
**「Type : Default - C++ Source」**
が原因でこのエラーは発生します。

エラーの内容を読むと

```
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.0.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:397:1: error: expected unqualified-id
@class NSString, Protocol;
^
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.0.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:399:19: error: unknown type name 'NSString'
FOUNDATION_EXPORT NSString *NSStringFromSelector(SEL aSelector);
```

とこんな感じなのですが、
噛み砕いて説明しますと、

**・C++のコード内にObjective-Cのコードが混ざっているのだが、そのObjective-Cのコードが認識出来ない**

こんなエラー内容になります。
また恐らくですが、**ファイル拡張子がcppの時のみ**発生するエラーなのでは無いかと思われます。

# 解決法
二通りあります。

### 1. ファイル拡張子を「.mm」に変更する
これはそのままですね。
ご存知の通り、.mmにすると自動的にObj-C++ファイルになりますので、
混在コードでもXcodeが自動で認識してくれます。

### 2. Typeを「Objective-C++ Source」に変更する
指定のcppファイルを選択すると、そのファイルのTypeを見ることが出来ます。
それを以下の通り、Objective-C++ Source に変えてあげればOKです。
![スクリーンショット 2014-10-26 19.28.10.png](https://qiita-image-store.s3.amazonaws.com/0/26453/712da9e1-a8ad-8a14-6fdb-997441dc3710.png)

これでビルドが通るようになります。

# 最後に
出来ればこういうエラーには出会いたくない…。
滅多な事では出会うことは無いと思いますが、
万が一出会ってしまった方の助けになれば幸いです。