onsen code monkey

個人的な日記とプログラミング備忘録です

【Swift】Timer処理まとめ

Swift4でのTimer処理関連を調べたメモ
モリー解放に気をつける

まずはTimer処理

final class ViewController {

    private var timer: Timer?                           // Timerを保持する変数
    private(set) var timerTotalDuration: TimeInterval = 0    // 総秒数を保持する変数

    func startTimer() {
        // ⑤ Timer のスケジューリング重複を回避
        guard timer == nil else { return }

        // ① Timerのスケジューリングと保持
        timer = Timer.scheduledTimer(
            timeInterval: 5,
            target: self,
            selector: #selector(handleTimer(_:)),
            userInfo: nil,
            repeats: true
        )
    }

    func stopTimer() {
        // ③ Timer のスケジューリングを破棄
        timer?.invalidate()
    }

    func resetTimer() {
        // ④ Timer のスケジューリングを破棄し、総秒数を0に戻す 
        stopTimer()
        timerTotalDuration = 0
    }

    @objc private func handleTimer(_ timer: Timer) {
        // ② Timer の間隔秒を総秒数に加算する
        timerTotalDuration += timer.timeInterval
        print("timer fired. total: \(timerTotalDuration)")
    }
}

View破棄時にTimerのメモリを解放する

override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        stopTimer()
    }


参考記事
【Swift】加算型Timer(ストップウォッチみたいな)の作り方 〜Timerの基本的な使い方〜 - Qiita
【Swift】メモリー対策!使ったタイマーは必ずinvalidate() - Qiita
【Swift】Timerの強参照が破棄できない時の対処法(deinit での破棄方法)│RC-Code

【Kotlin】スコープ関数 apply の使い方

例えば以下のようなコードがあったとする

val hoge = Hoge()
hoge.aaa = 0
hoge.bbb = 1
hoge.ccc = 2

hogeを4回も書くなんてナンセンスですね
そんなときはスコープ関数「apply」の出番です

val hoge = Hoge()
hoge.apply {
    aaa = 0
    bbb = 1
    ccc = 2
}

2回で済みました!

ヒューッ!!

【Kotlin】Null対策(Null Safety)

KotlinではNull Safetyという言語仕様があり、Null参照による実行時エラーを防ぐための仕組みがいろいろあるらしい

例えばnon-null変数(null不可)にnullable変数(null許可)を代入しようとするとコンパイルエラー

val nullable: String? = null
val nonNull: String = nullable // コンパイルエラー

でも!!演算子を使えば無理矢理代入することができる
(当然実行時エラーとなる)

val nullable: String? = null
val nonNull: String = nullable!! // 実行時エラー

僕はアホなので!!演算子フル活用で実装していたのですが
それじゃNull Safetyの意味がないだろとソースレビューで指摘されました
全くその通りです

Kotlin的にかっこいい書き方は以下のようにsafe call演算子(?.)とスコープ関数(let)を使うべきとのこと

nullable?.let {
            println(it) // nullじゃない場合のみ実行される
        }

たしかにかっこいい気がする

以上です

たまにしか更新しないといろいろブレる

まず一人称はなんだったか。私?俺?僕?
ですます調だったか。くだけた適当な感じだったか。
技術ブログ?趣味ブログ?ただの日記?

いろいろ忘れてしまうけどいちいち過去記事読み返して確認したりするのが面倒くさくて更新しなくなってしまうんだなぁ

急になにか書こうと思ったけど短文しか思いつかないなぁ

そりゃTwitterでいいじゃんってなるよね

【Kotlin/Java】0時0分0秒を取得する

UnixTimeStampでデータを管理することが多いのだけれど
とある日の0時0分0秒を指定したい時に毎回しばらく調べてしまうのでメモする。

Javaの場合

Date now = new Date(); // 2019-09-08 07:28:36
Date year = DateUtils.truncate(now, Calendar.YEAR); // 2019-01-01 00:00:00
Date month = DateUtils.truncate(now, Calendar.MONTH); // 2019-09-01 00:00:00
Date day = DateUtils.truncate(now, Calendar.DAY_OF_MONTH); // 2019-09-08 00:00:00
long unixTime = day.getTime() / 1000; // 1567868400

Kotlinの場合

val cal = Calendar.getInstance() // 2019-09-08 07:28:36
val year = cal.get(Calendar.YEAR) // 2019
val month = cal.get(Calendar.MONTH) // 8 (0から始まるので8=9月)
val date = cal.get(Calendar.DATE) // 8
cal.set(year, month, date,0,0,0)
val unixTime = cal.timeInMillis // 1567868400653

ライブラリを使うともっと簡単にできるっぽい。

ユーザーを騙して少しでも多く金を毟ろうとする悪質サービス

  • いつのまにか登録されているメルマガ
  • いつのまにか自動更新設定にされているサブスク
  • 退会申請がやたらわかりにくいサイト

等々...

ユーザーを騙して少しでも多く金を毟ろうとする悪質デザインを
ユーザーの意図しないアクションを誘導する悪質なデザインを「ダークパターン」というらしい。

無駄に名前かっこいいけど腹立たしい。
ダークパターンという名前は知らなかったけど、これらの悪質なデザインを採用しているサービスは二度と使わないようにしている。

せっかく良質なサービスを作っても意地汚いUXデザインのせいでユーザーの信頼を失っている残念なケースたくさんあるよね。

uxmilk.jp

【JavaScript】タイマー処理のメモ

<!doctype html>
<html>
<head>
<title>SPA</title>
<style type="text/css">
body {
width : 100%;
height : 100%;
overflow : hidden;
background-color : #777;
}

#spa {
position : absolute;
top : 8px;
left : 8px;
bottom : 8px;
right : 8px;
border-radius : 8px 8px 8px 8px;
background-color : #fff;
}
.spa-slider {
position : absolute;
bottom : 0;
right : 2px;
width : 300px;
height : 16px;
cursor : pointer;
border-radius : 8px 0 0 0;
background-color : #f00;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
(function() {
var requestAnimationFrame = window.requestAnimationFrame || 
                   window.mozRequestAnimationFrame ||
 window.webkitRequestAnimationFrame || 
                   window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();

(function() {
var cancelAnimationFrame = window.cancelAnimationFrame || 
                   window.mozcancelAnimationFrame ||
 window.webkitcancelAnimationFrame || 
                   window.mscancelAnimationFrame;
window.cancelAnimationFrame = cancelAnimationFrame;
})();


var startTime = new Date().getTime(); //描画開始時刻を取得
(function loop(){
//window.requestAnimationFrame(loop);
var requestId = window.requestAnimationFrame(loop); //戻り値を取得
var currentTime = new Date().getTime(); //経過時刻を取得
var status = (startTime - currentTime) // 描画開始時刻から経過時刻を引く
console.log(status);
window.cancelAnimationFrame(requestId); //戻り値をcancelAnimationFrameに渡してあげる
})();

var count = 0;
var countup = function(){
console.log(count++);
} 
var id = setInterval(function(){
countup();
if(count > 5){
clearInterval(id); //idをclearIntervalで指定
}
}, 1000);

setTimeout(countup, 7000);
</script>
<script type="text/javascript">
</script>
</head>
<body>
<div id="spa">
<form name="myform">
<input name="myfile" type="file"/><br/>
<textarea name="output" cols="80" rows="10"></textarea>
<h1>aaaa</>
</form>
</div>
<div class="spa-slider">aaa</div>
</body>
</html>