StarXpand SDKをインポートする（SwiftUI, Xcode）

今回はStarXpand SDKをXcodeでインポートしてみました。

**公式のサンプルではSwift×StoryBoardのソースしかないので、
SwiftUIに対応したい場合はこの記事を参考にしてください。**

※公式サイトのマニュアルは[こちら](https://star-m.jp/products/s_print/sdk/starxpand/manual/ja/index.html)

# 1.Xcodeプロジェクトを作成
まずはプロジェクトを作成しましょう。

![1-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511059/f036f6e8-32ed-26d1-8867-e894c295134d.png)

・Create a new Xcode projectを選択
・Appを選択してNext
・適当なProduct Nameを入力してNext
・プロジェクト保存先を選択してCreate

![1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511059/94544af9-910c-dfe3-4147-e9d685a63c28.png)

サンプルコードとともにプロジェクトが生成されました。

# 2.StarXpand SDKを取り込む
公式の導入手順は[GitHub](https://github.com/star-micronics/StarXpand-SDK-iOS/blob/main/docs/README_JP.md#%E5%B0%8E%E5%85%A5)で公開されています。

・File > Add Packages... を選択
・右上の検索バーに「star」と入力

![1-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511059/4b31bbd8-d3c6-9120-5319-a5d79493450e.png)

・StarXpand SDK iOSを選択してAdd Package
・StarIO10のチェックを確認してAdd Package

![1-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511059/2d5005bc-cc45-637c-96cc-3b6b8c03a178.png)

パッケージが追加されました。

# 3.必要な設定をする
info.plistの設定が必要です。

![1-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511059/efdaa0d8-484e-3813-5b4a-991726cc21aa.png)

他にもBluetoothを使用する場合、LANを使用する場合はユーザーに許可を要求するための設定をinfo.plistに入れなければなりません。

![1-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511059/a166d19c-cc9d-81c4-1368-5349586520eb.png)


# 4.SDKの動作を試してみる
今回はStarXpand SDKのディスカバリ機能を試してみます。
ディスカバリ機能とは、簡単にいうと周囲のプリンタを検索する機能です。

[リファレンス](https://star-m.jp/products/s_print/sdk/starxpand/manual/ja/ios-swift-api-reference/index.html)を見ると、ディスカバリ系のAPIは大きく3種類あります。

![1-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511059/f4b49927-1a00-435d-6df4-f591ea3ab075.png)

StarIO10をインポートします。
```swift
import StarIO10
```
No such module 'StarIO10'と出ても無視して大丈夫です。
一度ビルドすれば消えます。

続いてディスカバリ用のクラスを作成します。
StarDeviceDiscoveryManagerDelegateに準拠します。
Viewで監視するためObservableObjectにも準拠しておきます。

```swift:クラス全体
class DiscoveryManager: ObservableObject, StarDeviceDiscoveryManagerDelegate{
    @Published var printers: [StarPrinter] = []
    
    func manager(_ manager: StarDeviceDiscoveryManager, didFind printer: StarPrinter) {
        DispatchQueue.main.async {
            self.printers.append(printer)
            print("did find")
        }
    }
    
    func managerDidFinishDiscovery(_ manager: StarIO10.StarDeviceDiscoveryManager) {
        DispatchQueue.main.async {
            print("did finish")
        }
    }
    
    func discovery(){
        printers.removeAll()
        if let manager = try? StarDeviceDiscoveryManagerFactory.create(interfaceTypes: [.lan, .bluetooth, .bluetoothLE, .usb]){
            manager.delegate = self
            manager.discoveryTime = 10000
            do{
                try manager.startDiscovery()
            }
            catch{
                print("error")
            }
        }
    }
}
```

順に説明します。

```swift
@Published var printers: [StarPrinter] = []
```
検索したプリンターをここに格納します。

```swift
func manager(_ manager: StarDeviceDiscoveryManager, didFind printer: StarPrinter) {
    DispatchQueue.main.async {
        self.printers.append(printer)
        print("did find")
    }
}
```
プリンターが見つかるたびに呼ばれます。
StarDeviceDiscoveryManagerDelegateに準拠しているので必須です。

```swift
func managerDidFinishDiscovery(_ manager: StarIO10.StarDeviceDiscoveryManager) {
    DispatchQueue.main.async {
        print("did finish")
    }
}
```
検索が終了した時に呼ばれます。
StarDeviceDiscoveryManagerDelegateに準拠しているので必須です。

```swift
func discovery(){
    printers.removeAll()
    if let manager = try? StarDeviceDiscoveryManagerFactory.create(interfaceTypes: [.lan, .bluetooth, .bluetoothLE, .usb]){
        manager.delegate = self
        manager.discoveryTime = 10000
        do{
            try manager.startDiscovery()
        }
        catch{
            print("error")
        }
    }
}
```
検索を実行するメソッドです。
StarDeviceDiscoveryManagerFactoryはStarDeviceDiscoveryManagerを生成して返すAPIです。
生成されたStarDeviceDiscoveryManagerによって、startDiscovery()で検索を実行します。
検索時間は10000ms（10秒）としました。

続いてViewを実装します。

```swift
struct ContentView: View {
    @StateObject var manager = DiscoveryManager()
    
    var body: some View {
        List{
            Section{
                ForEach(manager.printers, id: \.self){ printer in
                    Text(printer.information?.model.description ?? "不明")
                }
            }
            Button("検索"){
                manager.discovery()
            }
        }
    }
}
```
検索ボタンを押したら実行し、検索したプリンターの一覧をリスト表示するというシンプルなViewです。

それではビルドして実行してみましょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511059/bb0d96b3-d51a-71f8-c5dc-2be6c4815c9e.png" width=50%>

検索ボタンを押すと

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511059/b80cb156-e10b-0db3-543c-fc8089c4fd61.png" width=50%>

プリンターが見つかりました。

出力を見てみると、プリンターが見つかった後も継続的に探しているようです。

![1-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511059/e536a0e0-e714-6248-eaad-f8ae5862f06e.png)

しばらくこのログが流れてきて、、、

![1-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511059/5d5b2338-dd7c-5117-dda3-27e92a046c65.png)

ちょうど、設定した10秒で終了の確認が取れました。

# まとめ
今回はStarXpand SDKをXcodeでインポートして使用する方法をまとめました。
まだまだたくさんの機能がありそうなので、色々試しながら記事で共有していきたいと思います。