2019年10月10日木曜日

ダークモードの回避

左が正常なのに、ダークモードだと右の表示になる
Labelの文字が白くなり、TextViewの背景が真っ黒に

iOS13とXcode11、macOS 10.15 Catalinaにした後にアプリを審査に出したら、表示が見づらいからってリジェクトされた。
なんじゃこりゃ、TextViewの背景色なんていじった覚えないぞ!? と思ったが、iOS13から付けられた(余計な)機能、ダークモードのせいだった。
どうやら新しく提出したアプリから影響するらしい。

UISegmentedControlの色もこのとおり

回避方法


Info.plistのUser Interface Style を Light にすればアプリ丸ごとこれまでのライトモードで動いてくれる。
親方様(アップル)としてはダークモードへの対応を推奨してるんだろうけど、また今度ね!
しかしどうしてこう、いちいちデベロッパーに無理な負担を強いるかなあ…。

2019年10月2日水曜日

ARAnchorの追加と削除

以下はARKit3とSpriteNodeで作る、XcodeのARのテンプレート(AR空間にインベーダー👾の絵文字スプライトを表示させるやつ)を基に直したもの。

ARAnchorの追加

Scene.swiftの方でARAnchorの位置を決めて
sceneView.session.add(anchor: )
すると、ViewControllerのARSKViewDelegateメソッド
view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode?
が呼ばれるので、そこで貼りたいSpriteNodeをreturnしてやると、それがAnchorに貼られるという変則的なやり方になっている。
実際にどうやってanchorにspriteを貼ってるのかは知らない。

Scene.swift

//カメラ前方の位置にSpriteを表示するためのanchorを貼る
func addAlienAnchor(sceneView: ARSKView) -> Void {
if let currentFrame = sceneView.session.currentFrame {
var translation = matrix_identity_float4x4 //世界座標と向きを表す4*4の行列
//前方の多少ランダムな位置を決定
//行列の3列目のz値に-0.4なら前方0.4m
let x:Float = 0
let y:Float = 0
let z:Float = -4
translation.columns.3.x = x
translation.columns.3.y = y
translation.columns.3.z = z
//カメラの向いてる方向に対しての表示位置を計算
let transform = simd_mul(currentFrame.camera.transform, translation)
//セッションに新しいARアンカーを追加
let anchor = ARAnchor(transform: transform)
sceneView.session.add(anchor: anchor) //sceneViewのsessionにアンカー追加
//アンカー追加によってViewControllerのdelegateが呼ばれる
}
}

ViewController.swift

引数anchorがこれからspriteを貼るanchor。

func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? {
//省略するが、ここにAnchorに貼りたいSpriteNodeを作り、returnで返す
return spriteNode
}

ARAnchorの削除

新たなARAnchorを貼るとき、または貼るSpriteNodeを作った時、anchorを管理用の変数に入れておき、削除が必要になったらそれを削除すると、それに貼り付いているSpriteNodeもろとも削除される。
sceneView.session.remove(anchor: anchor)

貼る時も削除する時も、sceneView.sessionに対してのメソッドを使ってるわけだ。

ARKitのカメラの露出を変えたい(今は無理っぽい)

以下は最新のiOS13、ARKit3でのお話。今後のことは知らん。

やりたいこと

夜の外とか暗いところでARKitで撮影すると、普通のカメラ撮影に比べてやたら暗いので、露出がコードから変えられないものか。

調べる

最初に、今のところ調べた結果ではカメラの撮影設定(オートフォーカスとかも)をいじれるAPIは公開されていないようだ。

明るい所ではシャッター速度を変えて露出を調節しているようだが(絞りまで変えているかは知らない)、暗い所ではスローシャッターの限界が1/60秒みたい。
ちなみにARカメラのシャッター速度は以下のコードでわかる。

if let currentFrame = sceneView.session.currentFrame {
let 露光時間 = 1 / currentFrame.camera.exposureDuration
print("露光時間 1/\(露光時間)")
}

たとえば晴れた昼間カーテンをした部屋の中だと1/60や1/90、青空だと1/4484、太陽に向けると1/10000。暗い押入れに向けた場合1/60だった。
あんまりスローシャッターにすると手ぶれで物体の検出に影響するから制限してるっぽい? ISO感度も変更しない?

結論

今は無理っぽい。
あんまり暗い場所での使用は推奨されないんだろうな。ARanchorにSprite貼って表示させても、距離感が狂うせいか勝手に大きさが変わったり、消えちゃうことも。
暗闇に浮かぶ宇宙人や幽霊を表現したいんだが、別のやり方考えなきゃダメか?