SwiftサードパーティライブラリをXamarinに取込む’24.5月Xcode14.1+vs2019Mac編

前回は、Xcode 15.1 と visual stduio 2022 for MAC で試し失敗しました。

一世代古い Xcode14.2 と Visual Stdio 20192 For MAC での組合せを確認します。

手順は同じですが、結果は変わりました。

いずれも Visual Stduio 側でダメです。NuGet で何か他にないか探すと少しでできましたが、いずれも古くて使えなさそうです。

以上、SwiftサードパーティライブラリをXamarin に取り込むのは、簡単にはいかないようです。Flutter はどうでしょうか? しかし調査時間がありません。しかたなくXcode + Swift で進めます。

iOSサードパーティライブラリをXamarinに取込む’24.5月Xcode15.1+vs2022Mac編

使いにくく品質の不安定な MAC / Xcode / Swift を避け、安定したWindow / Visual Stduio (Xamarin もしくは MAUI) で開発できれば効率向上します。appleの基本APIクラスライブラリは、Xamarinソリューション下の project名_iOS の中で、C#インターフェイスで呼び出せるようになっています。(apple一辺倒の方はこれをあまり知らないようです)

しかし、Swiftサードパーティライブラリ はこれに含まれていませんこれを解決する方法は Microsoftサイト 「iOS Swift ライブラリのバインド」 で説明されています。これを試してみました。結論としては、調査時間制限もあり上手くいきませんでした。どこまで何を確認したかの記録、ぜひ試したい方へのヒントになればと思います。海外含め「iOS Swift ライブラリのバインド」は情報がほとんどないのが実情でした。

記事は2、3年前に作られた記事のようですが、たまに更新されていたりします。現時点は ‘24.4月更新です。自動翻訳のせいで、Xcode の画面語句が日本語になってしまっていて難解さを増しています。Xamarinの後継MAUIについては取り立て説明はありませんでした。

Xcode15.2、Visual Stdiuo 2019 For Mac

iOSバインド記事メインページからリンクされている 「チュートリアル: iOS Swift ライブラリをバインドする」に従い進めます。ザックリとした手順は以下の通りです。

(1) Xcode にて サードパーティライブラリのframeworkプロジェクトを作成する。ここでTerm名noneにしないと後々ビルドでエラーがでます。

(2) 上記プロジェクトに、サードパーティライブラリを追加する。

(3) Geberal -> Framework and Liblaries にてサードパーティライブラリを”Do Not Embed” にします。

(4) BuildSetting -> All -> Build Options -> Allways Embed Swift Standard が no であることを確認。MS記事の bitcode は古い記述の模様。

(5) BuildSetting -> All -> Swift Compiler General -> General Header nameproject名-swift.h であることを確認します。

(6)公開したいクラスとメソッド定義を新規Swiftコードfileで作成します。引数型はSwitfとc#の型の互換性を確認し記述します。

( 7) メニュー Product -> Schema -> Edit Schema からダイアログを開き、Run > Build Configration でを release に変更します。

(8) MAC で、xodebuild コマンドを使ってビルドします。iOSシュミレータと実機用をビルドしxcframeworkに統合します。弊方は以下shスクリプトにまとめました。

以下の folder ができました。

(9) 古いMS記事では、lipo コマンドを使う記述がありました。同コマンドは実行バイナリコードの統合を行うものだそうです。 この統合は xcodebuild でも行えるようです。

(10) MACで、Objective Sharpie ツール をダウンロードし、MACにインストールします。これはMicrosoftがMAC用に作ったもののようです。これでC#とのリンク情報を作成する模様です。

(11) Objective Sharpie ツール を実行します。弊方は以下shスクリプトにまとめました。

以下の folder 下に .cs が生成されるようです。

(12) Visual Stduio 側でXamarinソリューションを作成し、iOSバインドライブラリのprojectを作成します。これ以降の操作はWindows版でも出来たと思います。

(13)上記(11)で生成された2つのfileを、ネイティブ参照にインポートします。コピー先はバインドライブラリの直下だったかもしれません。

(14)上記(1) のXcodeプロジェクトをネイティブ参照に設定します。

(15)Xcodeプロジェクトの設定を変更します。リンカーフラグの設定もしましたが最新情報ではないかもしれません。

(16)Xcodeプロジェクトの以下file設定を変更します。

(17)バインドライブラリを、アプリ本体側で参照設定します。

いちおうこれでMS記事の手順はできました。C#用インターフェイスを定義して、サードパーティライブラリを紐づけすればよいという感じのようです。バインドしたライブラリに対して、VS2022側でメソッド自動表示か応答するようになりました。

XamarinのiOSプロジェクトをビルドすると「Microsoft.iOS が無いというエラー」が発生します。下記CCLocationはiOSの位置情報クラスですので、Microsoft.iOS とはiOSライブラリのラッパーか何かのようです。

以下のようなエラーも出ます。

Microsoft.iOS を探してきて無理くり参照させると、

Apple側でなにか支障が生じるのではと予想していましたが、Visual Studio側で色々な矛盾が生じているようです。おそらくMAC OS、Xcode、Visual StudioとXamarinと周辺ライブラリのバージョンの組合せを一致させる必要があるのかなと思います。しかしその組み合わせはどこにも記載がありません。

次記事では別の組合せをためします。

Swift-UIでタイマで画面遷移する ‘24.5月編

Swift-UI にて、一定時間を待ち別画面に自動遷移する方法が、他記事に見つからなかったのでその覚え書きです。Xcode 14.2 です。

スプラッシュ(起動画面)中に特に時間がかかる初期化処理もなく、一瞬しかスプラッシュが見せれない。スプラッシュにはお客さんが作成したロゴとキャラクタを表示するのでこのままではまずい。しかしSwiftの画面遷移は自由度がないといったシチュエーションです。

更にスプラッシュにBackされては困ります。iOSではBackボタンがなくても、スワイプ操作でBackできてしまいます。

ます view の画面定義内でif文で分岐するという他言語では異常すぎるコードを書きます( 下図中※1 )。if文には任意のstate変数を定義して参照します。( 下図中※2 )

import SwiftUI
import Foundation
	
struct カレントtView: View {
    @State private var isActiveNextView = false     // 次画面遷移有無 ※2

    var body: some View {
         /* 次画面へ遷移する場合 ※1 */
         if isActiveNextView == true {
	            次のView() 	//  Memo: 次Viewを直callするとBack無効にできる ※1
         }
         /* カレント画面の場合 */
         else {
              VStack {
                     :
   	         カレント画面の定義
                     :

あとはvew表示イベントに待ち時間でTimerを仕掛けて( 下図中※3 )、その時間経過後、state変数値を変更します。( 下図中※4 )

   private var splashTimer: Timer!                 // 起動待ちtimer ※3
                     :
                   中略
                     :

             VStack {
                     :
   	           カレント画面の定義
                     :
             }
             .onAppear {
                  Timer.scheduledTimer(withTimeInterval:5.0, repeats: false){ _ in  // ※3
                      isActiveNextView = true    // 次画面に遷移 ※4
             }
         }
     }
}

違和感ありありですが仕方ないです。

なおコード表示には、Code Block Pro を使用させていただいたいてます。

Execlセル内でハッシュする

外部に提出しないExeclは効率UPのため2003を使用しています。最新のExeclでは、base64 エンコードくらいあるかと思っていましたがないんですね。win32APIを動的callできますが、Visual Studio 6 でインストールされる VB6用Declare 宣言をまとめた winapi32.txt に入ってない。手打ちは面倒なので検索すると、https://gist.github.com/rmdavy/db7cb6d81cc487172a86430f68633a21 に公開されていました。セル内使用に特化させ、コードが見にくい、エラー処理不足、32bit対応を直したので、ここで公開いたします。

しかし CryptAcquireContext 系は現在非奨励で、新しいのを使えとMicrosoft公開情報に掲載されています。いずれ調べたいと思います。

Execlセル内でbase64エンコードする

外部に提出しないExeclは効率UPのため2003を使用しています。最新のExeclでは、base64 エンコードくらいあるかと思っていましたが、ないんですね。「Execl base64」で検索してもあまり出てこなかったので、マクロExecl .xlm で作成しました。

Win32 APIの暗号化ライブラリで、API:CryptBinaryToStringA があったのでそちらの .dll を動的参照います。使用します。1コールでいけます。コードは以下の通りです。2003や32bit版offsice ビルドスイッチで切り分けています。URLセーフ(URLで使えない記号を置き替え、%xxのURLエンコードとはだいぶちがう) は、APIないので作りました。VBAエディタで「標準モジュール」に挿入します。

ちゃんとAPIエラー、引数エラー、VBエラー検出も組込みましょう。ネット上のサンプルはそれがあまりできていないようで実用上問題です。Execlの記述は、