TestFlightが届かないとき

前記事はこちら

TestFlight はどうも気まぐれです。ユーザさんから「招待が届かない」とクレームが沢山です。単純確立は1/5程度です。なんででしょう??? 注意点と対策です。

必ず別メールにて、招待した旨のメールをだしましょう。


この場合は、高い確率でTestFlightの招待が失敗する傾向があります。具体的な事象は、

開発者側から招待は成功し、「招待済み」の表示になるのですが、テスト者に招待が届かない

です。たたWEBページ低応答と同事象が常用的に発生してしてただけかもしれません。


再招待のボタンがあったので使ってみました。この時は効果はなかったです。


以下のようにパブリックリンクを有効にして、制限人数を設定し、URLコピーをテスト者にお送りします。こちらは有効な手段です。ただApple 審査が終わっていないとテストはできないため、Apple側の問題で招待がとどいていない場合のみ対策となります。

テスト者にコピーしたURLをメールで送る。


弊方では効果不明でした。

MAC操作性で困ってしまうとこ

MACは操作は人間工学に反しています。日本にあってません。もともとMACは急がすゆったり使う人用なのかもしれません。 日本社会では仕事用はWindowsなので、MACから切替えると業務支障をきたします。取引先がMACの場合も把握しておく必要がありそうです。その覚え書きです。随時更新中

ALT +ESC」に相当するものがない。Windowの切り替えランチャーみたいなものがありますが、選びたいんじゃなくて、とにかく考えずにめくってマウスを使わず次に操作するWindowに移りたいんです。いちいちクリックしてたら操作時間と考える時間を余計に消費します。


他PCでは「ESC」の位置なので習慣的に押しやすい、いろんなとこに予期せず「1」が入ってしまいますい、後で取り除かないといけません。「1」を沢山押すような社会的業務的要件は思いつきません。ブランクキーにでもしとけばいいのに… 邪魔すぎです。


キーボードに手を置くと、左下隅は小指の付け根あたりが当たりやすいです。他PCだと「Ctrl」なので単体で押す分には害はないです。しかし、MACはCAPS単体で CAPS ONになります。他PCでは、Shiftと同時に押さないと CAPS ON になりません。CAPS無効にはできるのですが、ディスクトップ機でApple純正無線キーボードを使った場合は効きません。「大文字小文字違いがそんなに重要?」と思われるかもしれませんが、Vi 使いにとっては非常に重要です。大文字小文字でコマンドが違うんです。意図せすCAPS ONになると、書いていたコードがぐちゃぐちゃになってしまいます。


いうまでもありません。古いMAC OSでは、Google日本語変換が使えていましたが、最新MAC OSではインストールしてもGoogleに切替えできなくなりました。


役にたたない「かっこいいでしょ」といわんばかりのアクション(「ソフトウェア芸」と呼びます)が、意図せず発動するとびっくりしますし本来したい操作の邪魔です。例えば、背景をクリックするとWindowが四方に散らばります。Windowが沢山のときディスクトップ上の何かが見たいとき一理ありるようにおもえますが、見たいWindowあるので強引です。Window移動のためタイトルバーをクリックして上にちょいスライドさせると縮小モードになりますが、何の意味もありません。


世界標準はGoole MAPでしょう。目標物などがMACのMAPは少ないようです。MACユーザがら送られていたMAPをみて、待ち合わせ場所に行こうとすると間違えてしまいました。周囲のコンビニが、Goole MAPでは2つ、MACでは1つでした。MACユーザがら送られていたMAPは信用せず、番地を聞いてGoole MAPで特定しておく必要があります。


リモートワークで欠かせないWIndowsのリモートディスクトップ。MACでも画面共有はありますが、画面だけなので、キーボート操作が変わってしまいます。特に日本語切替がリモート側でなく、ホスト側のみになってしまいます。


MACからWindows PCに戻るととても作業がはかどります。キーボートの応答性がわるいんですかね。


MACは、FreeBSDがベースだとか。CRオンリーのようです。基本UNIXマシンなんですね。昔HPや日立UNIXマシンもそうでした。MACユーザとtxtファイル交換時は要注意です。


MACがサーバ機になることはないでしょうから、ログインなしでshutdownさせてもいいんいでは? いちいち面倒すぎる。


「ALT+ESC」の件も含めて、マウスがないと何んも出来ない。MAC-miniをWindows Xamarinからbuildエンジンとして使うだけのとき、マウス繋いでないのでいちいちマウス接続を要してしまう。

Swift-UIでTable内容をリアルタイム更新する

Swift-UIでは 一画面のGUI最大表示数は 20個くらいです。それを超える情報を表示するには Table object を使うしかない。 そこで Table object に初期値を表示するWEB記事は多数ありましたが、リアルタイム更新する事例が見受けられませんでした。もしかして出来ない??? と思い試した覚書です。Xcode 14.1 です。

結論からいうと @State変数 を割当てれば普通に使えました。例では Foreground と Background でサーバとの通信の統計を表示する例です。

まず表示値を格納する@State変数を宣言します。

 	// 内部用の表示項目
 	@State private var	recvCnt 	 : [Int32]	= [0,0]
 	@State private var	recvErr 	 : [Int32]	= [0,0]
 	@State private var	sendCnt 	 : [Int32]	= [0,0]
 	@State private var	sendErr 	 : [Int32]	= [0,0]

Tableの列定義は、リアルタイム表示したい列は@State変数を定義します。

	// 統計コード列
	struct TokeiColums: Identifiable {
		let id = UUID()
		let name: String
		@State var value1: Int32
		@State var value2: Int32
		@State var value3: Int32
		@State var value4: Int32
	}

表示データの定義は、各列に表示値の@State変数を割当てます。

		// 統計行定義
		let TokeiInfo: [2] = [
			TokeiColums(name: "Server受信",
				value1: recvCnt[0], value2: recvErr[0], value3: recvCnt[1], value4: recvErr[1] ),
			TokeiColums(name: "Server送信",
			  value1: sendCnt[0], value2: sendErr[0], value3: recvCnt[1], value4: recvErr[1] ),	]

Table object の定義コードは以下です。縦余裕がないとさり気なく下から表示されなくなるため、一行余裕のある高さを指定おくのががベターです。

				/* 稼働統計 */
				Table(TokeiInfo) {
					TableColumn("項目") { locationColums in
						Text(locationColums.name)
					}
					TableColumn("OK件数-FG") { locationColums in
						Text("\(locationColums.value1)")
					}
					TableColumn("NG件数-FG") { locationColums in
						Text("\(locationColums.value2)")
					}
					TableColumn("OK件数-BG") { locationColums in
						Text("\(locationColums.value3)")
					}
					
					TableColumn("NG件数-BG") { locationColums in
						Text("\(locationColums.value4)")
					}
				}
			}

リアルタイム値の更新はタイマーで周期的に行います。

		.onAppear {
		   // タイマで3秒周期に更新
        updateDataTmr = Timer.scheduledTimer(withTimeInterval: 3,
							 repeats: true){ _ in
							 
					 		recvCnt[0] 	= 変更したい値
		          recvErr[0] 	= 変更したい値
		          sendCnt[0] 	= 変更したい値
		          sendErr[0] 	= 変更したい値
					 		recvCnt[1] 	= 変更したい値
		          recvErr[1] 	= 変更したい値
		          sendCnt[1] 	= 変更したい値
		          sendErr[1] 	= 変更したい値
				}
		}

表示例は以下のとおりです。

iPadでは特に問題はなかったのですが、iPhone では表示が真っ白でした。これは table object そのものの課題なのかもしれません。またタイマーは View をCloseしても生きています。必ず解放します。さもない View 再表示毎にタイマーが溜まってヤバイことになります。他言語ではVewとともに解放されますが、、、自分で停止するタイマを作る場合、インスタンスをGlobal定義し、invalidateで停止させないと効きません。タイマloop内で return も flg 値==falseでも脱出でできません。以下コード例です。

var    updateDataTmr:Timer? = nil     // 位置情報更新タイマ

struct ビュー名: View {
        :
       中略
        :
    var body: some View {
        :
       中略
        :
    }
    .onDisappear {
       if updateDataTmr != nil {
            updateDataTmr?.invalidate()     // タイマ停止
            updateDataTmr = nil
        }
    }

iOSでbackground定周期処理の実際のところ【’24.7月編】

iOS で background ( 端末画面が非表示のとき ) 処理を定期実行させることは鬼門のようです。Appleの情報、ネット記事、有識者の情報 どれも幾分違っていて真実が分かりません。iOSではバッテリ節約が最優先され、background 処理時間に制限が厳しいと言われているようです。 ’24年7月に実装した結果を報告します。

OSiPadOS 17.6
端末iPad 6th
Xcode実機TEST 15.1 、シュミレータTEST 14.2
言語Swift UI

基本 background は「アプリが前面に表示されていないが動作しているとき」ですが、完全なbackground状態にするには以下の配慮が必要なようです。

  • iOS系は 画面スリープ無し に設定できますが、これは有効にしないこと。
  • USBで電源供給したままにしない。
  • Xcodeと接続しない。

またプログラムに、

  • トレースログが取得できる仕組みを作成しておく。

取り掛かりとしてApp の onChange(of:scenePhase) イベント で background と foreground の切替りを検出してました。そのbackground のifスコープにで タイマーをつっこみました。(以下赤字部) これが一番シンプルかなと…カンで組んでみました。

一見動作しているように見えたのですが、途中でお亡くなりになるようです。background に移行してから動作可能な時間制限があるとのことですが、正確にどのくらいか色々試してもよく分かりませんでした。 UIApplication.shared.beginBackgroundTask ~endBackgroundTask を使って時間制限を検出しリカバリする方法も試しましたが、なんだか効果なしです。BGTaskScheduler というのもありますが有識者によると、「定周期background 処理は基本的ニ出来ない」とのことで試さずじまいです。

iOSで background 処理を定期的に行う手法として、GPSによる中心座標からの半径範囲(リージョン)への出入りを検出する方法が、いろいろと紹介されています。これは XamarinのiOS Background処理の説明ページにも記載されています。概念図は以下の通りです。

もちろんこれが適用されるのは、端末がある程度の時間経過とともに移動するシステムに限ります。その検出部のコードは以下のような感じです。

ポイントとしては、

  • 移動しないとBackground実行できません。
  • 定周期でBackground実行する場合は、移動量と時間のCONVERTが必要です。
  • 半径5mに指定しても、イベント発生させるには50~100mくらい移動を要します。
  • UIApplicationDelegateAdaptor を Appクラスで絡めるコード例もありますが、シンプルに CLLocationManager だけで構築できます。

リージョン出入り検出」は、秒、分単位の定周期処理とすると不向きのようです。通常、リアルタイム緯度経度の検出で使用しているCLLocationManager のイベントも、よく観察するとBackground時でも動作していることに気付きました。リアルタイム緯度経度検出 と Background処理を一緒に行えば、もっと早い周期でBackground処理が可能となります。その検出部のコードは以下のような感じです。

ポイントとしては、

  • 移動しないとBackground実行できません。
  • 定周期でBackground実行する場合は、移動量と時間のCONVERTが必要です。
  • 移動距離をもっと小さくすると、秒周期でBackground内でイベント発生させることも可能。(iPadではGセンサも併用している模様)
  • 日中での電池の持ち、iPadなら電池の持ちは心配ない感じ。iPhoneは厳しい感じ。
  • 移動イベント中に、新しい移動イベントが発生した場合、新しい移動イベントは保留される。(保留最大数は未知)
  • リージョン出入り検出と同居可能。

Background内である程度の周期で動作できるようになったら、何秒くらい動作可能か情報が必要です。これも色々な説があるようです。以下のBackground処理ダミーコードで調べてみました。下記コード中の printLog はローカルtxtファイルへの出力付きの print 関数の自作ラッパーです。5秒置きにlogを残すことでどこまで動けるか確認しました。

結果としては、

  • 最小で45秒までは動けてはいた。公称値が30秒とのウワサ。
  • 最大120秒程度まで伸びる場合あり。CPU使用時間が影響しているのかもしれない。
  • 許容時間超過後、TASKは休止状態となり、Foregroud移行後に動き出す。
  • 製品コードでのBackground処理はScokect通信です。これはうまくいきました。

iOSでMQTT通信を使う ‘24.7月編

IoT用通信で利用されるMQTTですが、 iOS で適用する案件があり対応したので要点の覚え書きです。MQTT Broker が何なのかは知らされておりませんが、汎用的なものだと思います。

AWSでは各プロットフォーム毎にライブラリが提供されていました。汎用タイプのMQTTとなると使えるのは以下の2とおりでした。Get/Post methodのように、各プラットフォームで公式APIは未だ無いみたいです。いづれもOpenソースなので信頼性は要注意です。

ライブラリプラットフォーム公開URLMQTTバージョン備考
MQTTnetXamarin / Visual Studiohttps://github.com/dotnet/MQTTnet3.1.0、3.1.1、5.0指定可。.NetSockectがコアのためiOSでも動作する。
Xamarin.MQTTXamarin / Visual Studiohttps://github.com/xamarin/mqtt指定不可。開発止まっている。MQTTnetを簡易callしたもので利用価値低い。
CocoaMQTTSwift / Xcodehttps://github.com/emqx/CocoaMQTT3.1.1、5.0指定可。
iOS, macOS, tvOS native ObjectiveC MQTT Client FrameworkSwift / Xcodehttps://github.com/novastone-media/MQTT-Client-Framework最終更新日が4年前

上記から現用と思われる2つを確認してみました。

最新 4.3.4.1xxx はConnectで落ちました。ここ一か月間で頻繁にコード更新がかかっています。怪しい。一つ前のリビジョンで一年前くらい 4.2.0.706 をchoiceし通過しました。.net 的なネーミングですが、Microsoftが管理しているわけでもなんでもないようです。

NuGetで「最新安定版」と記載されていても、だれも安定しているか確認していないのかもしれません。

尚、各クラスとmethod/propertyの使い方説明はなく、サンプルコード を見て理解してといった感じです。

iPadOS16互換で、Xode 14.2互換でXcode 15.1です。こちらも最新は落ちました。Gitでバージョン切替えながら試すと、2.1.7 で落ち着きました。


BSD Socket は、CocoaAsyncSocket MqttCocoaAsyncSocket の2つがあり指定できるのですが、後者でないと動きませんでした。下位ライブラリは、MqttCocoaAsyncSocket 1.0.8、Starscrem 4.0.4 でした。

こちらも各クラスとmethod/propertyの使い方説明はなく、Example をみる感じです。今回は他ライブラリが Swift でないとダメでしたので、CocoaMQTT を適用しました。MQTTnet より以下の機能メリットがみられました。

  • サーバ自動接続モードあり。再接続インターバルの指定などもできる。ただ永遠ではない。
  • デバッグモードあり。有効にすると Xcode コンソール に、JSON送信データなどがプリントされる。
  • MQTTnet では未トライですが、SSLモードもすんなりOK。

すこしコードを紹介すると、

ただし接続できたかは、ステータスを監視する必要があります。送信時は、

iOSからMQTTを使用した結果、以下の課題がありそうです。

  • 端末起動直後、インターネットネットにつながっていない期間があるため、MQTT接続のリトライが必要です。 ラズパイ等の場合、shで自由にUNIXコマンドで監視管理できますが、iOS下では自由度がありません。iOSのインターネット接続状態の取得API NWPathMonitor も確実性がないようてす。

またMQTT全般的にいえることですが、

  • サーバに Publish が未到達でも端末側では分からない。そもそも MQTT は高信頼性を目指したものではないのですが、実際に発生するとエンドユーザは怒ります。信頼性仕様の協議と取交わしが必要でしょう。再送やユーザに通知したい場合、サーバ側のカレントデータを読みだしてベリファイするインターフェイスを追加するとが必要だと思います(サーバ側の協力があれば)。もしくは最初からHTTPや独自protocolにしとく。

また標準ポート番号 SSL無し:1883、SSL有り:8883 は特に問題なく使えました。Appleゆえポートを開ける設定が必要かと思案していましたがそんなことはありませんでした。