Xcode 10.0:結構変わった
iOS 12 がリリースされたので、Xcode もバージョンアップしないと iOS 12 のアプリが作れないので、必然的にバージョンアップされる。早速ダウンロードしてインストール。
アプリがちゃんと動くことを確認し、さて、何が変わったのかと色々試してみる。editor 画面のフォントが変わったのかなぁ、少し見やすくなった。あと、dark mode っての?背景を黒にするやつ、Mojave で推してくるのでやってみた。
Preference > Font & Colors > Default (Dark) を選択。背景色が黒になる。みやすいのかなこれ。暗いので目には良さそうに思い、しばらくこれで試してみることにしよう。Console の背景色も黒になるのがちょっとイヤなのですが、ま、しばらくはこれで・・・
ヴェポライザーでシャグ :DAISO シリコーンマウスピース
100 円ショップでライターを買おうと思い、喫煙具コーナーを見ていると、シリコーンマウスピース(P・T)と言うのが売ってた。7 個入りで ¥100 ととてつもなく安い、紙巻きたばこ一本より安い。プルーム・テック用に作ってあるようだけど、C Vapor 2+ でもマウスピースにつけられるのではないか、あるいは煙管の吸い口にも合うのではと思い買ってみたら、これ、当たり。
まず、C Vapoer 2+ で吸った時の温度が少し下がる感じ。通常 210 度で加熱しているのですが、唇が気持ち火傷する感があるのが、マウスピースを付けるとちょっと温度が下がるように思う。
次に、味が格段に濃くなるのでうまい。一度加熱してうまい、時間が来て終了、即 5 回プッシュで再加熱してもまだ味を楽しめる。マウスピースのおかげで一度煙が集合する感じになるので、これが味濃くなっていいみたい。
デフォでマウスピースついていればいいのにと思った。
メモリーリーク:Xcode と Instruments:その2
カメラを使うアプリを作っていて、メモリリークでアプリが落ちる、それを調べるのに Instruments が有効だと書きました。でも、Instruments で検出できない leak もあり、memory をモニタリングしつつ使われている method を掌握しつつ、根本的な問題解決へ向け、色々調べ、ようやく分かりました。
delegate method の captureOutput:didOutputSampleBuffer:fromConnection 内で UIImage を生成。この delegate method は、カメラ(厳密には movie)使用中、ガンガン呼ばれているのを確認。delegate method 内で生成した UIImage が解放されず、どんどんメモリを消費。終いにはメモリを食い尽くしてしまい、安全面から OS に kill される・・・と、まあ、このような現象だと。頼むよ ARC・・・。
原因がわかったので対策を。
使い終わった UIImage を解放してやればよいのですが、ここでハマる。CGImage の場合、ご丁寧に、CGImageRelease() という method ? primitive? が用意されている。さて、UIImage の場合は UIImageRelease だろ、と思ったら、そんな method は存在しない・・・うっっ どうすんのこれ。苦肉の策で someUiImage = nil; とかしてもダメ。ネットを検索してみたら、ARC が利かないなら @autoreleasepool を使え、とのことで、いろいろやってみたけれど、状況は改善せず。叱られると思いつつも、[someUiImage release]; とかやって、やっぱり叱られる。release は ARC に任せてくれよとか言ってくる始末。任せたけどダメだったからやってんだろと、文句を言いたくなる。
ここで脳内に神降臨。こんな方法を思いつく。
CGImageRelease( someUiImage.CGImage );
CGImageRelease が通るように、無理やりCGImage を生成するという荒技。これが功を奏し、アプリが落ちなくなった。
Instruments でメモリ監視すると、メモリが騰がったり下がったりで、うまく機能しているようだ。
正しい方法かわからないけれども、上手くいったのでこれでよしとしよう。ってか、頼むよ ARC ・・・
メモリーリーク:Xcode と Instruments
アプリを作っているのですが、
カメラに写った画像を加工してどーのこーの
というのをやろうとしてて、アプリを起動し、しばらくすると落ちる。原因は、起動しているとメモリを食い過ぎてしまい落ちているようだ。
メモリリーク・・・水道管の水漏れにちなんで、メモリ漏れといったところか。
さて、どこが問題なんだ?と調べるには、便利なアプリが用意されていて、Instruments を立ち上げて、Leak でアプリ起動中のメモリ状態をモニタリングできる。しかも、leak した箇所について印まで出る丁寧ぶり。
慣れないながらテキトーにいじっていたらなんとなく深く調べられた。どうやら問題点は、
CGContextRef
のような primitive と言うのですか、C 言語由来の関数を使ったら release してやらないとダメっぽい。丁寧なことに、CGContextRelease という関数まで用意してある周到ぶり。ARC じゃなかったっけ? primitive には通用しないのか・・・
早速試して見たら、騰り一本調子だったメモリがガクッと下がる、また騰がって下がる、あ、うまくいったかと思ったら、また落ちた・・・
Leak の印は no leak に変わっているので、問題は解決したように思いますが、検出できない問題があるようで・・・
厄介だなぁ。さて、また調べますか。
SpriteKit の touch event と座標変換
SpriteKit の Scene では縦方向の原点が下で、UIView では上になるという違いがある。なんでそんなことすんの?という疑問なんですが、SpriteKit はゲームで利用することが多く、重力を計算するとき原点が下にあった方が理解しやすいからなんだろうなと勝手に想像をしています。
それは置いておくとして、実務上、touch された位置を取得してその位置に object を移動させよう、なんてことを考えると、原点どっちだ?というのを気にしないといけません。単純に上下反転すればいんじゃ無いの? と思いがちで、始めその線で書いてみたんですがどうにも動きが不自然。
なんかいい方法ないのか?と探したところ、Apple の document を参照すると、locationInNode という便利な method があるじゃないですか、こんな感じで。
UITouch* touch = [touches anyObject];
CGPoint newLocation = [touch locationInNode:self.scene];
この class は SKShapeNode の sub class なんで、self.scene がそのまま通るとは思わなかったのですが、通ってしまえばこっちのもの、よしとしよう。
CGRect を配列の要素にするには・・・
どうも CGRect には泣かされる。CGRect を配列の要素にしようと思い
[mutableRects addObject:textObservation.boundingBox];
とすると以下のエラー
Sending 'CGRect' (aka 'struct CGRect') to parameter of incompatible type 'id _Nonnull’
仕方がないので、次のようにするとエラーにならなかった。
[mutableRects addObject:[NSValue valueWithCGRect:textObservation.boundingBox]];
う・・・これめんどくさい。