VS2022 17.10からmacOS14.4.1にiOSアプリのクロス開発お試し

Visual Studio 2022 にて、Xamarin、MAUIではなく、iOSアプリケーションというProject項目があったので試してみました。たとえSwiftでもWindows上から開発できれば効率UPします。

まずプロジェクトを追加してみます。

ちなみにiOSライブラリをXamarinでつかえるように調査時に登場したキーワード iOSバインドライブラリ は2つでてきますね。

スケルトンができたので、何か追加してみます。

言語はC#になるようですね。

そのままBuildしてみると、、、

.net 8 (7?)が無いらしく、それを追加インストールしてBuild。

よく分かりませんが以下のようなキャプチャも記録していました。

結局以下のエラーでふんずまってしまったようです。

結局、よくわかりませんでした。

Visual Studio 2019 Setup Projectのインストーラ作成手順まとめ2

前記事では、Visual Studio Setup Project で基本的なインストーラ作成手順をまとめました。本記事ではオプション的な設定方法を記述していきます。


吊るしの状態では殺風景ですし、サプライヤとしてアピール不足です。以下のようにインストーラ画面にバーナーを追加が可能です。

(1) 左図アイコンを開きます。

(2) 各インストーラ画面のプロ
パティから左図のようせ選択
します。

(3) 画像を追加します。インストーラー実行時に展
開されていたような覚えがありますので、
Application Folder を選択しておいた方がよいでし
ょう。.png や .gif など透過性は使えないようです。
全インストーラ画面でこの設定を行います。
画像は 約720 x 120 pixel で作成します。


Windows Installer ではインストール後、Windowsレジストリにエントリが作成されます。以下のように必要に応じてカスタマイズ、追加が可能です。

(1) 左のアイコンを選択します。

(2) デフォルトで、サプライヤ名のエントリが作成されます。これはプロジェクトのプロパティの
Manufacturer の設定値です。AlwaysCreate は基本 ture に変えます。

(3) 一般的にサプライヤ名の下に
プロダクト名のキーを作りま
す。InstallShieldなどは自動作成
します。こちらは手動作成が必
要です。[ProductName]
Windows Installerの予約変数で、
プロジェクトのプロパティの
ProductName の設定値です。

(4) インストールされたディレクトリをレジストリに追加しておくとアプリ側で色々と活用できます。その場合は以下のように操作します。[TARGETDIR] は Windows Installer の予約変数でユーザが指定したインストール先を示します。

(5) インストールされたバージョンもレジストリに追加しておくとアプリ側で色々と活用できます。その場合は以下のように操作します。[ProductVersion] は Windows Installer の予約変数でプロジェクトのプロパティの ProductVersionの設定値です。将来のUpdate時に、過去にインストールされたバージョンが分かるとデータの移行判定などに活用できます。

(6) インストール後のレジストリ内容は以下のようになります。これでInstallShieldと同等のレジストリエントリとなります。


ユーザが誤ったバージョンのインストールを防止したり、トラブルシューティング用にインストーラバージョンはどこかに表示しておきたいものです。以下のようにインストーラ画面の文言の変更が可能です。

(1) 左図アイコンを開きます。

(2) [ようこそ] 画面の WelcomTextを変更します。”Adminstrative install“の方も直しておきます。

(3) 変更値のサンプルは以下のとおりです。[ProductVersion] は Windows Installer の予約変数でプロジェクトのプロパティの ProductVersionの設定値です。プロジェクトのプロパティ Localization Japanease でもデフォルト値は英語ですが、変更する場合は日本語を指定しないといけません。

この度は本製品をお買い上げいただきありがとうこざいます。 [ProductName] ver.[ProductVersion]のインストールを継続するには、”次へ(N)>”をクリックします。


(1) User Interface のタブから以下のように追加します。

(2) ライセンス文を .rtf 形式で指定します。


Custom Actionのタブに追加します。インストールとパラレルでVBScript呼出すことは可能でした。しかしVC++ 2005ランタイムがインストールされているかチェックしたかったのですが、VBScript では厳しいようです。InstallShieldのカスタムアクションDLLや専用スクリプトには及ばないようです。

.exeのアクションも試したようでしたが結果は忘れてしまいました。あまり有効ではなかったのでしょう。。。


日本語版と英語版の2つをリリースすることはよくあることかと思います。日本語版から英語版を作る手順は以下のとおりです。InstallShieldなどは、一つのインストーラ定義から多国語のインストーラを生成できますが、こちらはそこまで対応してないようです。

(1) Visual Studio Setup Project のソリューションに、英語のSetup Projectを追加します。

(2) 日本語Projectの各種設定を、英語Project に転記します。Projectファイルをコピーして直接エディタで修正するのでもよいかと。

(3) 英語Project のプロパティLocalization English に変更します。

(4) 日本語版と英語版を同じプロダクトとして扱いたいなら、ProductCodeUpgeadeCode はも合わせておいた方がいいでしょう。(未だ未トライです)

(5) 全体構成は以下のような感じです。


以上、Visual Studio Setup Project である程度実用的なインストーラは作れました。しかし開発環境が用意できない、手がたりない、自身がない、担当者がいなくなったなどお困りの方は、こちらよりご相談ください。

Visual Studio 2019 Setup Projectのインストーラ作成手順まとめ1

Visual Studio Setup Project によるインストーラ作成手順の覚え書きです。高価なインストーラビルダーを導入しなくても、シンプルなアプリなら対話的に作成がです。難解な Windows Installer のAPIを使いプログラミングしなくとも。Visual Studioのエディションは、Professional です。


標準インストールでは入っていないのでPackageを追加します。

メニュー 機能拡張 -> 機能拡張の管理 を開き、Visual Studio Studio Installer Project を探し追加します。なお 2019 と 2022 で機能差は無かったです。

メニュー ツール -> ツールと機能の管理 からではないので注意です。ただ追加後、当メニューから追加済みの確認はできます。

新しいプロジェクトの作成から、Setup Project を選び、以下のように操作します。


(1) アプリfolderに配布する
exe、icon、その他
dll.ocx、設定ファイルなど
を右click menu”Add“で配
置します。

(2) プログラムメニューを
追加します。サプライヤ
名、プロダクト名が一般的です

(3) アプリexeのショートカ
ットを作成します。

(4) 上記(1)で配置したファイルの中
から選択します。

(5) ショートカット
名をプロダクト名
に変更します。

(6) アプリICONを指定しま
す。上記(1)で配置したファ
イルの中から選択します。

(7) プロジェクト設定を項目に従い入力しま
す。InstallAllUsesは基本tureです。PC全体に
一つインストールするという意味です。マルチ
ユーザインストールはアプリ構造も管理も面倒
になり、一般的につかいません。デフォルト
falseなので必ず変更します。

UpgradeCode は Update Installerを作るときの
一意の同一プロダクトを示すキーです。管理記
録しておく必要があります。
Vsesion は Update時には、大きい値でないといけないので、 その時を想定して付与し
ておく必要があります。メジャー. マイナー.リ
リース(Build番号) 形式のみ。数値以外はNGで
す。Manufacturer ProductNameはインスト
ールパス、レジストリキーにも影響するため弊
方では記号はさけるようにしています。
自動的に切替わったりはしないので
Localization はリリースする国に変更します。

(8) 左図アイコンを開きます。

(9) InstallAllUsestureでか
ら変更できないように、イ
ンストール時画面からその
選択を非表示にします。

(10) アプリのユーザ設定値ファイルなど、ア
ンインストール後も残すファイルは、
Permanent True にしておきます。


Debug」Buildは意味ないので「Release」Buildのみ使用します。setup.exe ( .msiのランチャー、OS毎の互換性を吸収するためだったと記憶) と .msi ( Microsoft Installer形式 : インストーラ本体) の2つが生成されます。本プロダクトでは、Install Shieldのように一つの Setup.exe にまとめることはできません。

デバックは通常のアプリとはことなり、メニュー プロジェクト -> インストール より行います。Install Shieldは実インストールされないですが、こちらはされてしまいます。

インストール時の基本的な画面の流れは以下のとおりです。

アンインストール時の流れは以下のとおりです。


以上、これで最低限のインストールが一応できます。しかし本当に使えるインストーラを作るには、以下のような追加設定等が必要です。 これらは Visual Studio Setup Project でもできます

  • 使用許諾文画面の追加。
  • 画面バーナの追加。
  • レジストリキーの追加。
  • 次バージョンでのアップデート対応
  • 英語対応
  • カスタムスクリプト

ということでVisual Studio だけでインストーラは対話的に作れました。しかし開発環境が用意できない、手がたりない、自身がない、担当者がいなくなったなどお困りの方は、こちよりご相談ください。

Swiftでviewを非表示状態にするには?

Swiftでviewを非表示にして、アプリを常駐化したい。他記事にはストレートな答えがみつからなかったため、TRY&ERRした覚書きです。

.NET など同じセンスで書くと、、、 NGでした。

self.hidden() // 効かない、警告でる -> NG

Swift固有の命令をつかってみます、、、NGでした。

dismiss()   // Loginにもどってしまう。-> NG

iPhone / iPad の Home画面に戻します。なるほど...これならアプリを起動したままviewを非表示にできますね。発想を変える必要があったのですね。

 // 結局のところ非表示にはできない。 Home画面に戻す -> OK
  UIControl().sendAction(#selector(URLSessionTask.suspend), to: UIApplication.shared, for: nil)

SwiftでSHA256ハッシュ+Base64+URLセーフエンコードを行うには

サーバ屋さんが MQTT ClientID SHA256ハッシュにくわえ、Base64+URLセーフエンコード にしてくれと言われるので調べて対応した覚え書きです。単にユニーク値で記号を含まないなら、SHA256だけでもいいと思うのですが... こだわりか既存のサーバの作込みがそうなってるのかなと...

Swiftでも、SHA256ハッシュ、Base64 のAPIはありましたが、URLセーフエンコードはなく、これはロジックで組む必要がありました。またこの3段階変換を行い、デバッグ用に中間変換結果も確認しするには、少々オブジェクトの選択扱いがややこしいようでした。コードは以下のとおりです。

  public func ConvertKey(
		baesKey: String, 	// 変換対象のキー
	) -> String
    {
        var ret: String = ""
        
        //--- SHA256値をBase64にエンコードし、URL safeにする。---
        let srcBin:Data?    = baesKey.data(using: .utf8)    // Binaly変換 
        let hashVal         = SHA256.hash( data: srcBin! )  // SHA256ハッシュ (内部はByte配列)
        let hashBin:Data?   = Data( hashVal )               // Binaly変換
        
        // 生成結果のDBG用の確認トレース
        let hastStr = hashVal.compactMap { String(format: "%02x", $0) }.joined()
        print( "HASH=" + hastStr + " len=" + String(hastStr.count) )
        
        // URL64エンコード 
        if let stg1 = hashBin?.base64EncodedString() {
            // Memo: Swiftには、URLセーフAPIはないため、ハンドコードで変換する。
            let stg2    = stg1.replacingOccurrences(of: "=", with: "" )
            let stg3    = stg2.replacingOccurrences(of: "+", with: "-")
            ret         = stg3.replacingOccurrences(of: "/", with: "_")
        }
        else {
            print( "base64EncodedString() error.")
        }
        
        return ret
 }

一旦、Binaly値に変換してあげるとスマートに収まりました。

gtestでfloat値をExecl計算値と照合を試みる

gtestでテスト対象モジュールで計算されたfloat値を正しく計算されたか、Execl計算値と照合するケースは多いのではないでしょうか? floatは32bitですが数値分解能は23bit(確か…)、longの方が精度が高く、実際にはあまり使わないものです。今時のPCや携帯端末では、doubleを多用してもへっちゃらです。

しかし、マイコン向け組込みソフトでは未だdoubleを多用できるほど処理能力がありません。MATLAB/simulink の自動コード生成の都合で float(single) は使う場合もあるようですが、そもそも浮動小数点数は自体あまり使うべきではないと考えますが…

とあるお客さまで、gcc 使用でfloat値 不一致が多発していたので少し調べてみました。調査は VC++2019 で行っています。


Execl計算値をそのまま EXPECT_FLOAT_EQ に指定した場合、指定した数値から精度が落ちたことを警告されます。なるほどgccよりvc++の方が賢いみたいですね。テストはgccと異なり合格になります。Execl2003はVC++でBuildされてるでしょうから同じコンパイラから生成された数値は一致しやすいのでしょうか?


Execl計算生値では精度が大きすぎるようです。値をVBAマクロでfloat(Single)化した値をEXPECT_FLOAT_EQ に指定してみると、精度が落ち切っていないようです。


Execlに精度をあわせて EXPECT_DOUBLE_EQ を使うと上手くいくのでは? と思いましたが、float -> double 拡張で数値が変わってしまうようです。


ということて面倒ですが数値公差範囲を決めて、 EXPECT_NEAR を使しかなさそうです。EXPECT_FLOAT_EQ の公差は 4 ULPs (Unit of Last Place: 下4桁?) 以内にとのこと。

BungBungame KALOS のカスタムROM化は可能か?

ユーザさんより台湾BungBungame製 KALOS のカスタムROM化が可能か問合せがあったため調べてみました。その覚え書きです。

年式2013、当時日本でもいろいろ紹介されていたようです。現在、情報も少なく、スペックはこちらのようです

Android4.22止まり、有機EL、2560×1600と解像度は当時としては高く、Wi-fiモデルのみ。

https://androidfilehost.com/ にも直接はヒットせず。しかし「BaikalOS」といキーワードが出てます。これはAndroidの派生の一つのようです。たまたま単語部分一致でヒットした模様です。
2013年製となると、どのみち最新に近いAndroid相当のROMは作られていないと思われます。

SwiftではTextEditorの縦サイズが端末毎に変わってしまう

Shitf-UI にてライセンス許諾文を、TextEditor に表示した際の覚え書きです。Xcode 14.1 です。

TextEditor は、オートサイズが無いようです。フォントサイズを指定して、ライセンス許諾文が収まるようTextEditor 横縦サイズを指定しておきました。理論上どの端末でも同じになるハズですが、端末によって、ライセンス許諾文が途中で切れてしまいます。 これは iOSシュミレータと実機での間でも発生します。付随条件としては、TextEditor だけはスクロールできないので ScrollView をかませました。この時の端末は iPad 6th です。

@State private var licenseText : String = "Error"
 :
中略
 :
var body: some View {
 :
中略
 :
    ScollView( [.vertical], showsIndicators:true) {
	     TextEditor(text: $licenseText/* $必須 */ )
	     .frame(	width: myWidth * 0.9, height:8000)
	     .disabled(true)	// 入力禁止有効 
    }
    .border(Color.black, width: 1)
 :
中略
 :
}
.onAppear {
   :
  ライセンス文読込み
   :
	licenseText = tmptxt.string
   :
 後略

おそらく端末毎に dpi が異なるためだとおもうのですが、dpiを取得して演算するまで凝りたくありません。表示領域が多い分には実害はないので、弊方では height値 を一番高性能そうなiPad Pro 12inch の iOSシュミレータで合わせこんでおきました。

    ScollView( [.vertical], showsIndicators:true) {
	     TextEditor(text: $licenseText/* $必須 */ )
	     .frame(	width: myWidth * 0.9, height:9000)
	     .disabled(true)	// 入力禁止有効 
    }

8000 -> 9000 にUPで収まったということはザックリ1割のマージンを持たせておいた方が無難という感じでしょうか?

Swiftでフォントに影をつけるには

Swift-UIで、画面タイトルなどちょっとフォントを装飾したい。しかしフォント装飾の機能は何も見当たらない。Appleだからこジャレた装飾がたくさんあるのかと想像していましたが... ちゃんとタイトル画像を作ることがAppleポリシーなのでしょうか? そこまでは労力を掛けたくない。

そこで以下のようにすると、ZStack でノーマルフォントとボールドフォントを重ねると、フォントに影がついて少し見た目がよくなりました。

	/* アプリVersion、等長fontでBoldを下にひいて影付け */
	ZStack {
		// 下側(影)
		Label(	"Version 1.5.5",
			systemImage: "")
		.font(.system(size: 36, weight: .bold, design: .monospaced))
					
		Label(		"Version 1.5.5",
				systemImage: "")
				.font(.system(size: 36, weight: .regular, design: .monospaced))
        .foregroundColor(Color.yellow)
	}

表示例は、

ちょっとイマイチかもしれませんが、プレーンな状態と比べるとかなりマシです。

Swiftでは画像縮小時、縦横比が保持されない

Swift-UIで画像を縮小表示する場合、アスペクト比を保ったまま表示されませんでした。htmlでさえ幅か高さだけ指定すれば、アスペクト比を保ったまま表示してくれるのに… その対策か他記事では見当たらなかったので報告します。 Xcode 14.1 です。急いでいたので幅広く調べてはいません。

対策は、オリジナル画像の縦横サイズを確認して、コード上で縦サイズと横サイズをアスペクト比を保つように計算します。

let bounds = UIScreen.main.bounds
let myWidth	 = bounds.width		// 自画面幅

Image("picture")
.resizable()	// Memo: コレ付けないと原寸表示される。
// Orignalサイズ 1664 x 1912 から画面サイズで計算する。
.frame(width: 1664 * myWidth/1912  * 0.35 ,
 	     height: 1912 * myWidth/1912 * 0.35 )
.padding(20)

複数の端末種に対応させるために、スクリーン横幅基準にズーム率を乗じます。

う~ん、本当にこれでいいのか? 面倒すぎる。