本記事について
この記事は CoreBluetoothForUnity Advent Calendar 2023 の14日目の記事です。
Swift の標準ライブラリには String, Array, Dictionary などの基本的なデータ構造が用意されています。
Unity のネイティブプラグイン開発において、これらではなく Foundation にある NSString, NSArray, NSDictionary 等を使うとできることについて紹介します。
環境
- CoreBluetoothForUnity 0.4.4
Foundation とは
Swift で import Foundation
すると使えるフレームワークです。
インポートすると、NSString 等の NSxxx という名前のクラスが使えるようになります。
CoreBluetoothForUnity 0.4.4 では例えば以下のクラスを使っています。
- NSString
- NSNumber
- NSArray
- NSDictionary
NSBool はなく、NSNumber が 0, 1 で論理値を表現します。
なぜ NSString 等を使うのか
Foundation フレームワークの NSString 等のクラスは、標準ライブラリの String 等と比較して、Unmanaged 型への変換が容易である点が大きなメリットとなります。
Unmanaged 型 を取得する passRetained の引数はクラス(= AnyObjectを継承している)です。
標準の String は値型のため passRetained の引数にはできません。NSString はクラスなため可能です。
実際のコードは以下です。
@_cdecl("ns_string_new")
public func ns_string_new(_ str: UnsafePointer<CChar>) -> UnsafeMutableRawPointer {
let nsstring = NSString(utf8String: str)!
return Unmanaged.passRetained(nsstring).toOpaque()
}
このように、NSString を用いることで、Swift と C# の間での文字列やデータの受け渡しを簡単に実現できます。
NSArray や NSDictionary でも同様です。
Foundation のリポジトリの READMEにも、この「クラスであること」のメリットが書かれています。
They provide reference semantics instead of value semantics, which is a useful tool to have in the toolbox.
基本的な機能なため、ネイティブプラグインが複数あると重複する
0.4.4 時点の CoreBluetoothForUnity では、Foundation フレームワークの基本的な機能を含んでいますが、
Swift のネイティブプラグインを複数プロジェクトに入れると重複してしまいます。
上記の例では ns_string_new
という汎用的な名前を使っていますが、これだと衝突しそうなためもっとユニークな名前をつけた方が良いかもしれません。
直近優先度は高くはありませんが、将来的には CoreBluetoothForUnity から Foundation 部分は切り出そうと思っています。
おわりに
本記事では Swift のネイティブプラグイン開発において Foundation フレームワークの NSString 等を使うとできることについて紹介しました。
Swift 始めた時は import Foundation
に何の意味があるのか全然わからなかったため、ネイティブプラグインの開発過程で良さがわかってよかったです!