エンターテイメント!!

遊戯王好きのJavaエンジニアのブログ。バーニングソウルを会得する特訓中。

2019/12/16週 気づきと振り返り

業務こなしての問題・気づき

iphoneで、xcodeでビルドしたアプリが起動できない

「このAppは信頼~」をしてないって思って、実行したら、「ネットワーク接続されてません」って出た。
wi-fi繋がってるよな~って思って、入切を繰り返しても、「ネットワークが接続されません」が出る。。。

なんで?って思いながら画面を見渡していたら、時刻が超ズレていた。。。。
時計を合わせるようにしたら、問題解消。。。

もうちょい親切なメッセージを出してくれって思いました。。。。

firebaseのユーザ削除

web上で、firebaseのユーザを削除したが、iphone上は、まだ有効なユーザとして使えた。。。
原因を探ると、ローカルで保持している情報があるらしい。
1時間毎にチェックするため、即時で使えなくなるってわけではない。
ユーザ情報を取得する際は、クラウド上のデータを見るのか、ローカルのキャッシュのデータを見るのか、考える必要がある。

tableviewのcell

cellForRow(at: <IndexPath>)で非表示のセルを取得した場合、nilが返ってくる、

雑記

ポケモンGo

ポケモンGoがたまごっちみたいになってきたな。。。
遊んだり、きのみ上げたり、たまごっちやってる感覚に近くなってきた気がする。

いま、まだたまごっちって生き残ってるのかな?
たまごっち、デジモン妖怪ウォッチは、すべてポケモンに駆逐された印象。

服が。。。

乾かない!
私服は4着しかないから、溜めて洗濯すると、スーツで出勤になってしまう。
どうやって乾燥させればいいんだ?
扇風機は、この時期使うのは、死を意味する気がする。
空調は、電気代節約のために使いたくない。
う~ん。。。選択肢がない気がする。。。

ipadでSidecar

試そうと思ったら、macが2015年のやつだった。。。
普通にデュアルディスプレイするしかないのか。。。
せっかく、ipadのスタンドを買ったのに。。。

年末

どう過ごそう?
テレビは廃棄したから、「笑ってはいけない~」は、見れないんだよね。
何かを一気見しようかな?候補としては、ゾンサガ、ギアスあたり。

年始は、一般参賀行くくらい。

家で、AdventCallendarの内容閲覧するだけで終わりそう。。。
近場の温泉でも行くかも。

UItableViewのセルに配置した部品のデータの管理方法

きっかけ

「テーブルで部品を配置して」と仕事上頼まれて、配置したはいいが、項目が表示されないときにnilになることを忘れていて、金曜日の定時間際に慌てて修正しようとしたけど、パニックって時間だけ浪費して終わってしまったので、土日にじっくり勉強したので晒す。

余談

じっくりと言っても、ジャンフェスとか行ってきたから、実際は、あんまり時間をかけてない。
というか、ジャンフェス混みすぎだろ。。。
終わり間際に行ったつもりだったのに、3時間待ちとか聞いてない。
10年くらい前なら、終わり間際はガラガラだよってのを聞いたのに。。。。
鬼滅のせいか?
やたらと鬼滅って単語が物販列に並んでる最中に飛び交ってた印象がある。

実装

完成品は、下記のgithubにあげてます。

https://github.com/suzaku-tec/swift-sample/tree/master/table-layout-sample/TableLayoutSample

パニックった経緯

最初は、iphoneXの画面上にテーブル内のセルの全部の項目が表示されており、firebaseに入力されたデータを登録していた。
なんかく実装できていたので、余裕じゃんって思ってて、調子ぶっこいて、だらだらテストしていた。
で、「別端末で表示しても大丈夫だよな?」って思って、iphone8で実証を始めた。
AutoLayoutを利用することを心がけていたので、事象が起きた画面に遷移するまでは、全然レイアウトの問題はなかった。
問題の画面に到達。
そうしたら、テーブル内のセルが一部非表示になっていたが、気にせず入力してfirebaseに更新する処理を実行したら、例外が。。。
スタックトレースの内容を見ていると、なぜかnilにアクセスしようとしていて落ちていた。
対象のセルは、画面に非表示だった一番最後のセル。
意味がわからなかったので、再現性を確かめるべく、スクロールして値を入力してみたら、今度は、画面に表示の最上部のセルがnilで落ちた。。。

最初は、取ってくるところが間違っていると思ったが、それならiphoneXでも発生するだろうと思って、悩んでいたが、画面に非表示になるとエラーになるということに気づいて、真因が分かった。
ただ、原因が分かったからと言って、対応方法が分かったというのは、別問題なのよね。。。

対応方法を考えているうちに、時間だけが過ぎていき、パニック状態に。。。。

対応方法

実際の現場で試したわけではないが、大まかな対応方法を検証できた。

対応としては、protocolで独自のイベントを作って、セルの編集イベントを検知したら、tableViewにイベントを通知して、ViewControllerに保持しているdatasourceに入力内容を保存するようにした。

作ったprotocol

protocol InputTextTableCellDelegate {
    func textFieldDidEndEditing(cell: BaseCell, value: String) -> ()
}

イベントの検知方法

cell側

class BaseCell: UITableViewCell, UITextFieldDelegate {
    
    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var textField: UITextField! {
        didSet {
            textField.delegate = self
        }
    }
    
    var index: Int = -1

    var delegate: InputTextTableCellDelegate! = nil
    
    func textFieldDidEndEditing(_ textField: UITextField) {
        print("textFieldDidEndEditing")
        self.delegate.textFieldDidEndEditing(cell: self, value: textField.text!)
    }
}

作ったプロトコルを保持しておき、TextFieldの変更イベントを検出したら、protocolを叩くようにしている。 ※self.delegate.textFieldDidEndEditing(cell: self, value: textField.text!)の部分が実際に通知している箇所

table側

extension ViewController: UITableViewDelegate, UITableViewDataSource, InputTextTableCellDelegate {
    func textFieldDidEndEditing(cell: BaseCell, value: String) {
        datasource[cell.index].text  = value
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        datasource.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = table.dequeueReusableCell(withIdentifier: "base") as! BaseCell
        
        let index = indexPath.row
        
        cell.label.text = datasource[index].label
        cell.textField.text = datasource[index].text
        cell.index = index
        cell.delegate = self
        
        return cell
    }
}

前述した func textFieldDidEndEditing(cell: BaseCell, value: String) が、セルが変更あると叩いてくるので、このメソッドの中で、datasourceの値を更新するようにしている。
delegateの設定とかの話は割愛

SwiftのTableの実装は厄介

Swiftのテーブルは、非表示になるとリソースを有効活用するために、非表示のセルをcellForRow(at: <IndexPath>)で取得するとnilが返ってくるものらしい。
以前も同じ轍を踏んだ気がする。。。
でも、再度表示すると値が残っているから、てっきり、cellForRow(at: <IndexPath>)でいつでも取得できるものだと勘違いしてしまった。
cellForRow(at: <IndexPath>)は、誤解を招きやすいので、削除してもらいたい気分。

テーブルを使う際は、いつでもセルが復元可能なように、データを実装側で管理する必要があるってのは、常に頭に入れておく必要がある。
それに伴って、swiftのAPI的に、セルを取得するようなメソッドは、削除してもらいたい。
入力保管で開発をやってると、結構な確率でドツボにハマる気がする。。。

雑記

protocolの知識が怪しい。。。
やりたいことの通知方法の概念は分かっているのだが、いざやるとなると戸惑ってしまう。
分かっていても、実際にやれるとは限らないんだなって痛感した。。。

参考サイト

【Xcode】文字入力できるTableViewCellサンプル - 文系プログラマの勉強ノート

大変助かりました。

2019/12/09週 気づきと振り返り

業務こなしての問題・気づき

[Swift] XLPagerTabScriptを使ってみて

  • 設定が面倒くさい
    • 少なくとも2クラスは必要
  • 制約が多い
    • UIScrollView
  • UIや動きは、すごくキレイ

[Swift] UILabelで改行をstoryboardで入力

control + Q + enter

ctrl + Enterで何回かやって、なんで改行されないのだ?ってなった。
たぶん、2・3日したら忘れると思う。。。

[Swift] Timer.scheduledTimerをfireする

Timer.scheduledTimerをfireすると、タイマーが起動するのではなく、タイマーが発火する。
fireの意味を考えれば、たしかにそうだが、最初に使ったときは、起動させる箇所がなかったので、fireでTimerが起動するのかと思った。
おかげで、結構悩んでしまった。。。

[Swift] delegateの設定

delegateの実装をしたあと、delegateの設定を忘れるため、実行しても機体動作にならなくてドツボにハマってしまった。。。
delegateの実装で満足してしまうのよね。。。

これは、どうしたら防止できるのだろうか?

UILabelで角丸

Attributeにlayer.cornerRadius を設定するだけでは、角丸にならない。
Clip to Bounds にチェックを入れる必要がある。

Clip to Boundsが曲者。
よく設定し忘れて、なぜ角丸にならないのかドツボにハマることがたまにある。
これを覚えても、翌週には綺麗サッパリ忘れるのが痛い。。。
設定箇所を一つにできないものなのだろうか?
コード上でやるしかない?

雑記

剣盾のレイドのカビゴン

倒せぬ。。。
倒せるときもあるけど、だいたい苦戦する。
じしんとか、全体攻撃は卑怯だろうと思うのは、僕だけか?
キョダイサイセイとかも、威力が高くてやめて欲しい。

ひとりプレイしかできないのだが、どうすればいいのだ?
ムゲンダイナ使ってるけど、味方がポンポン倒される&シールドが突破できないから、アーマーガア使うようにしたけど、全然効率が上がらない。
2,3回やってやっと倒せるくらい。

アカウント失効

アカウントが失効してしまい、入館できないわ、Jira見れないわ、PCにログインできないわで、成果が出しにくい一週間であった。。。

2019/12/02週 気づきと振り返り

業務こなしての問題・気づき

macgithubの大文字小文字の区別

swiftで小文字始まりでプロジェクトを作って進めてしまい、swiftlintを適用した際に、大文字始まりに変えろと怒られた。
それで、大文字始まりに変えてgit addしようとしたら、差分が出てこなかった(気がする。時間がたってしまったので覚えてない。。。)

ディスクのフォーマットを確認したら、APFSの大文字小文字を区別しないになっていた。。。
この場合は、リネームは、git mv を使って、一回別な名前のフォルダに変えてから、本来変えたいフォルダ名に変えるとできる。

この回答に辿り着くのに、かなり時間がかかった。。。

参考サイト

https://dev.classmethod.jp/etc/mac-apfs-ignore-case/

Jenkinsのジョブコピー

{Jenkins_Home}/job配下に、ジョブ名のディレクトリがあるので、それをコピーした後、jenkins再起動でコピーしたジョブのコピーができる。

なんか、邪道っぽい気がしないでもない。
これが頻発するようなら、ジョブ生成を自動化するほうが無難な気がする。

参考サイト

kakakikikekeのブログ: Jenkinsで他のJenkinsにジョブをインポートする方法

Jenkinsの履歴削除

  1. {Jenkins_Home}/job配下にある、対象ジョブのディレクトリ配下のbuildsを削除する。
  2. nextBuildNumberの内容を1にする。
  3. echo 1 > nextBuildNumber でやるのが簡単

参考サイト

kakakikikekeのブログ: Jenkinsでビルド履歴をすべて削除する方法

gstreamでOGGとmp4を組み合わせた結果

Gstreamでrtpで配信された映像と音声を合成するようなコマンドを作っていた。

音声をOPUSをOGGに変換して、映像はh264をmp4に変換して合成するようにしていた。
しかし、ファイル出力はされるが、Quick Timeで再生ができなかった。
いろいろ調べた結果、相性的な問題だったり、環境的な起因で再生できなかったりしている様子。

音声をOPUSからwav形式に変換して合成したら、うまく再生できるようになった。
wavにしたのは、サポートされている環境が多そうだったから。

とりあえず再生できたから、細かいことを気にするのは辞めた。
時間が取れたら、詳しく調査する。
年末あたりにできるかな?

雑記

アメ玉

喉が痛くなる季節になってきたので、よくアメ玉を舐めるようにしている。
ただ、なめると、すぐに噛み砕きたくなる。。。
ストレス溜まってるのかな?

ポケモン剣盾のワイルドエリア

これは、ヤバい。
中毒性が。

やり始めると止まらない。
マックスレイド回ってる最中に、シンボルエンカウントポケモンで新しいの発見したりすると、テンションが上がる。
ポケモンGoのゲーム内完結型だと思う。

2019/11/18週 気づきと振り返り

業務こなしての問題・気づき

マルチキャスト配信

ルータがマルチキャストに対応している必要がある。
IPv4はオプションなので、いまの段階だと確実性に欠けそう。

公式ドキュメント大事

ググった結果の情報が正しいとは限らない。
ググる前に公式ドキュメントを見るほうが大事。

gstreamerが分からん。。。

どれを使えば目的が達成できるのか分からん。。。

gst-inspectであたりをつけて、パイプラインでつなげて試す以上のいい方法はないのだろうか?

雑記

JJUG CCC Fall

行く予定だったんだが、家出た時の雨風の強さに断念した。。。
台風並みだった気がするが、他の人は大丈夫だったのだろうか?

資料はあとで読まなければ。。。

2019/10/28~11/4週 気づきと振り返り

業務こなしての問題・気づき

APIキーのベタ書き

Github等でソースコード管理している場合、コードにAPIキーをベタ書きするべきではない。
プライベートリポジトリであっても、誤操作で公開してしまうリスクがあるので、なるべく避けるべき。

普段のコードでも、ベタ書きはやらない方がいい。
受け渡しは、環境変数を使うなど、コードから間接的にアクセスするような手間をかけておくと、流出のリスクは減る。

rubyのThreadの生存確認

ライブラリ調査で、サンプルコードを試しているのだが、そのコードがrubyで書かれてあった。

Threadを使う機会があり、コードが動かなかったときにプリントデバックで確認していたら、スレッドの生存確認をしたくなった。
rubyでどうやるのか調べたところ、thread.alive?で確認できる。

最初、使ったときは、?を入れてなくて、実行時エラーになって、相当悩んだ。
最後の?がキモすぎだろ。。。って思ってしまった。

rubyで、Address already in use

rubyでソケット確率の処理を書いていたら、Address already in useが出てきた。
読んだ通り、すでに利用中という意。

macだったので、lsof -wni tcp:{ポート}で調査して対応した。

docker stopで全てのコンテナを止める

docker stop $(docker ps -q)で全て止められる。
何をやっているかと言うと、docker ps -qで起動しているコンテナのIDを取得して、そのIDを docker stop に渡している。
docker stiopは、複数のコンテナIDを指定可能なのでできる。

JenkinsでGithubからソースコード取得するさいのビルド指定子の指定なし

最終コミットを取得するようになる。

webAPIをcurlで叩く

No contents応答であることの確認は、レスポンスヘッダを見ないと分からない。

雑記

docker psのps

プロセスの略だと思われる。

最初見たとき、プレステ?フェイズシフト?とかの発想にしか至らなかった。。。

ブログの更新

毎週書く予定だったのに、1週間飛ばしてしまった。。。
金曜に書くように努力していたのだが、ついつい先延ばしにしてしまう。。。

これは全て、P5Rが悪い。
やり始めると、辞め時が分からない。
気づくとその日が終わってしまっている時がある。

まだ途中までしかやってないけど、オクムラパレス、ニイジマ・パレスのボス戦がキツかった。

シドウパレスは、現在攻略中。

ポケモンの剣盾発売前までには終わらせたい。
今月は、Gジェネもあるんだったな。。。
当分、休みは部屋から出ない日が続きそう。。。

2019/10/21週 気づきと振り返り

業務こなしての問題・気づき

Jenkins Job DSL

最近、Jenkins使ったCI環境の構築をしている。
jenkinsしている途中で、いろいろ動的な処理をしたくて調べていたら、Jenkins Job DSL が使えるんじゃない?ってなった。
でも、やりたいことができなくて、よくよくドキュメントを見ると、Jenkins Job DSLって、ジョブを作るための言語で、ジョブの処理を記述するやつじゃないじゃん!ってことに気づいた。。。

これで、1日潰してしまった。。。。

結局、シェルでガシガシ処理を作ることになった。
シェルが分からないわけではないのだが、いかんせん、記述方法が独特で、実装がかなり面倒くさいんだよね。。。

xcodebuildでBundle identifierを変える

Appleのフリー開発者アカウントで、Jenkinsのビルド設定をしていたのだが、いざビルドするとなると、No profiles for ‘XXXXX’ were found が発生していた。
ローカルでやるときは、勝手に変えてたけど、jenkinsでやるときにどう変えたらいいのか、結構迷った。

xcodebuild 時に、CODE_SIGN_IDENTITYPROVISIONING_PROFILE を設定してやれば、なんとか突破できる。

雑記

twitterの個人アカウントのフォロー

特定の個人のフォローは、情報収集という意味でフォローするのは、やめたほうがいい。
大抵の場合、どうでもいいツイートのほうが多くて、結構なストレスになる。

情報収集するなら、企業か組織のアカウントをフォローするほうが、無難。

呼吸を意識した睡眠

最近、なかなか寝付けなくて困ってた。
夜になると、悪いことばっかり考えてしまうんだよね。。。

いろいろ調べて試した結果、呼吸に集中して眠るって方法が一番自分に合ってた。
寝る前にゆっくりと深呼吸をして、呼吸することだけに意識を集中すると、すんなり眠れる。
呼吸を極めたら、俺も柱に成れるかな?