t__nabe_log

雑多 作業、学習ログ多め。

Arrayに対する処理をglobal queueで行った時の順序について

SwiftのDiscordコミュニティはレベルが高い。実務経験1年弱の自分の今のスキルと大きく乖離があるので自分で調べ直して理解しないといけない現状。 そこでSwiftのDiscordコミュニティで話をされていたことで自分がすぐに理解出来なかったこと且つ興味の湧いた所を定期的に残していきたいと思う。Scrapboxとの使い分けにいまだに悩む

配列に対するメインスレッドでの並列処理

import Foundation

var array = Array(repeating: 1, count: 100000)

DispatchQueue.global().async {
  array.insert(3, at: 99999)
  print("inserted")
}

print("start")
let total = array.reduce(0, +)
print(total)
print(array.count)

これの実行結果が以下。Command line executable

# 順番は実行するたびに変わる恐れあり
start
inserted
100000
100001

Command line executableの場合のmain()は生のmain。 dispachMain()を自分で呼ぶなどしないとDispachQueueの支配するメインスレッドにならない。のでlet totalの行は指定しているqueueの中で実行されていない。

DispatchQueue.asyncの並列実行は、発火しても、スケジュールされるかどうかは運次第なので、asyncが実行される前にarray.reduceが終わってしまう可能性があります。 https://discordapp.com/channels/291054398077927425/291211035438874625/504148932818108419

これに関しては今まで開発で使ってきたので納得。

global dispatch queueはconcurrent queue。オブジェクトが1つだとしても。QoSについてはEnergy Efficiency Guide for iOS Apps: Prioritize Work with Quality of Service Classesを参照。

Arrayはスレッドセーフなのか

明確にスレッドセーフと書かれているわけではないらしい。デフォルトで非スレッドセーフで特に何も書かれていないから、スレッドセーフではないと考えられる、とのこと。

Collection Types — The Swift Programming Language (Swift 4.2)

OwnershipManifestoには

The most important consequence of this is that two different array elements cannot be simultaneously accessed. This will interfere with certain common idioms for working with arrays, although some cases (like concurrently modifying different slices of an array) are already quite problematic in Swift.

[OwnershipManifesto.md#subscripts] (https://github.com/apple/swift/blob/master/docs/OwnershipManifesto.md#subscripts)

arrayの異なるsubscriptにconcurrentに同時にアクセスするのはNGという言及がされている。Discordでは同時にという表現ではなく、concurrentにという表現だったがドキュメントからconcurrentにとは読み取れなかった。

そもそも自分がスレッドセーフという概念を正確に理解しているのか心配になってきた。

スレッドセーフ(Thread-safe)は、マルチスレッドプログラミングにおける概念である。あるコードがスレッドセーフであるという場合、そのコードを複数のスレッドが同時並行的に実行しても問題が発生しないことを意味する。特に、ある共有データへの複数のスレッドによるアクセスがあるとき、一度に1つのスレッドのみがその共有データにアクセスするようにして安全性を確保しなければならない。

スレッドセーフ - Wikipedia

Thread-Unsafeは任意のオブジェクトが同時に複数のスレッドによって変更を許可する場合。 Thread-Safeは任意のオブジェクトが同時に複数のスレッドで変更を許可しない場合。 Immutableなobjectsは基本スレッドセーフって考えて良さそうだなとか考えてたがAppleの公式ドキュメントがあるのでこっち読んだほうが良い。 納得したのでArrayの話に戻る。といってもスレッドセーフじゃないことを確認するコードを書くだけ。

こんな風に複数のスレッドで変更しようとすると警告が出る

import Foundation

var a = [1,2,3]
DispatchQueue.global().async {
    a.append(5)
}
DispatchQueue.global().async {
    a.append(6)
}
// Fatal error: UnsafeMutablePointer.deinitialize with negative count

別の変数に同期をとると回避出来る。

import Foundation

var a = [1, 2, 3]
var b = a
DispatchQueue.global().async {
    a.append(4)
}

DispatchQueue.global().async {
    b.append(5)
}

Arrayはスレッドセーフじゃないと認識して良さそう。

SwiftではArrayやDictionaryはCopy on Writeになっているがスレッドセーフじゃないのか?

In Swift, Array, String, and Dictionary are all value types. They behave much like a simple int value in C, acting as a unique instance of that data. You don’t need to do anything special — such as making an explicit copy — to prevent other code from modifying that data behind your back. Importantly, you can safely pass copies of values across threads without synchronization. In the spirit of improving safety, this model will help you write more predictable code in Swift. Value and Reference Types - Swift Blog - Apple Developer

同期をとることなく安全にスレッド間で値のコピーを渡すことが出来るとのこと。CoWという仕組み自体はスレッドセーフと考えてよさそう。

CoWの実装方法は@omochimetaruさんのSwift での Copy on Write の実装方法の解説 - Qiitaという記事がわかりやすかった。

WordpressのCSSにタイムスタンプを追加して古いキャッシュを読み込まないようにする

WordpressCSSにタイムスタンプを追加して古いキャッシュを読み込まないようにする

PHPの経験もなく、殆どWordPressを触らないので備忘録代わりに残す。

開発環境で問題なく表示されたCSSを本番環境にも適用した後に反映されないことがあるのを解決したかった。 ブラウザでキャッシュを削除したら変更が反映されるのだが、自分のブラウザのキャッシュを削除するのは手間がかかるし、利用者にそれを強いるのは問題外。 WordPressについて調べていると、CSSのURLのクエリパラメータにタイムスタンプを付与することで、CSSの変更の度に再読み込みが行われるようにするのが一般的なようだった。 以下のようにするらしい。

header.phpに追記する方法

【修正前】

<link rel=”stylesheet” href=<?php bloginfo (‘stylesheet_url’); ?>type=”text/css” />

【修正後】

<link rel=”stylesheet” href=<?php bloginfo(‘stylesheet_url’); echo?. filemtime( get_stylesheet_directory() ./style.css’); ?>type=”text/css” />

これで解決したというサイトが多かった。 しかし、自分が保守することになったWordpressのサイトはwp_head関数を通してCSSを読み込んでいた。

  • wp_head関数で読み込んでいるCSSにタイムスタンプを付与する
  • wp_head関数ではメインのCSSは読み込まないように変更してwp_head関数にタイムスタンプ付きのCSSを読み込む処理をフックさせるか

上記2つのどちらかで対応しようと考えた。 とりあえず解決するのが目的で、アプリの開発に戻りたかったので後者の方で進めることにした。

以下のコードをfunction.phpに追記。

// wp_head()ではstyle.cssは読み込まない
function delete_css() {
    // ブラウザのコンソールで読み込まないようにしたいcssのidを確認してwp_dequeue_styleの引数に渡す。
    wp_dequeue_style('sitename-style');
}

add_action( 'wp_enqueue_scripts', 'delete_css' );

// style.cssをタイムスタンプ付きで読み込む関数
function get_timestamp_include() {
  // style.cssのパスを取得
  $styleurl = get_bloginfo("stylesheet_url");  
  //style.cssのタイムスタンプ取得
  $styletime = filemtime( get_stylesheet_directory() . '/style.css'); 
  //タイムスタンプ付きstyle.cssを読み込む
   echo '<link rel="stylesheet" id="sitename-style-css" href="',$styleurl,'?',$styletime,'" />'; 
}
// wp_headにフックさせる。
add_action('wp_head', 'header_stylecss_include');

終わり。

Google Homeを買った。

ついにGoogle Homeを購入

以前から欲しかったので買ってしまった。 https://i.gyazo.com/5af0321a1d46238da2ed9440de71e04d.jpg

正直舐めてた。Spotifyを気楽に再生・停止、TwitterやSlackに音声で呟き、各種ストリーミングサービスの再生や料理レシピ、買い物リストなどを使っているが本当に生活が楽。気をつかうことが減るのは良いことだ。

参考にしたサイト

Google Home で音楽を聴く - Google Home ヘルプ

  • 音楽を手軽に聴けるようにするのが一番の目的だったのでまずここを読んだ。

Google Homeで好きなポッドキャストをスマートに再生する - Qiita

  • Rebuild fmを聴きたかったので。

10分でSlackからGoogleHomeを喋らせるめちゃ速レシピ - Qiita

  • Slackへの投稿方法。Twitterもこれを参考に作った。

Smart Home - Scrapbox

  • 徐々にスマートホームにしていきたいと思っているので読んでいる。他の人が作ったScrapboxは読むハードルが上がる印象があったが1テーマで絞ると非常に見易い。

今後やりたいこと。

  • 簡易なサーバでNode.jsを動かしてGoogle Homeで遊びたい。
  • スクレイピングしたテキストを読みあげてもらいたい。
  • スマートホーム化
  • Google HomeをきっかけにRasberry pi等にも興味が出てきたので触ってみる。

「プロを目指す人のためのRuby入門」を読み終わった。

f:id:nabeatsu1:20171210192706j:plain 一度読んだから汚く移ってる😥

伊藤淳一さん(@jnchito)の「プロを目指す人のためのRuby入門」を終えることが出来ました。 Rubyを触ったばかりのころからQiitaの記事でお世話になっていたのでこの本が発売されるということを聞いた時からやってみたいと思っていました。

学習時の自分のスキル

メディア事業をやっている企業で管理職をやりながら、3月から基本情報の勉強がてらにCASL2の勉強を始めたのがプログラミングの初めての経験。

その後5月から未経験でプログラマとして転職。業務で学習時間を設けてもらった後にRuby on Railsで小規模な社内システムを開発。その後RailsでWebアプリケーションを制作した後にAPIを作って、iOSからそのAPIを利用するためのアプリをSwiftで2月完成目標に開発中。

「プロを目指す人のためのRuby入門」を始めたきっかけ

  • 最低限のRubyの知識は業務の過程で身に付けたものの、わからないことがあった時はその都度周辺の知識を含めて調査という感じで開発を続けていたので、このあたりで一度Rubyの体系的知識を頭に入れておきたかった。

  • テストコードを今まで書かずにコーディングしていて、そろそろテストコードの書き方を勉強しようと思っていた。

  • Railsアプリケーションの開発をしているのにRubyについて場当たり的な対応で得た知識のままでいるのはどうかと思った。

進め方

  • 1度目ということで記載されているプログラムは全て自分の環境でも書いてみる

読んだだけで使えるようにならないのはプログラミングを始めてから身に沁みているので、必ずこれは行うようにしました。

  • 紹介されていたリンク等を1度は目を通す

これは単純に楽しいからです。以前読んだReal World HTTPの時にもそう感じたので今回も紹介されたリンクは積極的に読んでみることにしました。覚えようとはしていないです。

nabeatsu.hatenablog.com

このようなやり方で進めたので、読み終えるまでに2週間程度かかってしまいました。 もっと気楽に1周した方が良かったのかなぁとちょっと思ったりしました。

使用頻度が少ないと事前に記載されている

個人的にはテスト駆動開発を体験出来るということと並んでありがたいと感じたところです。

一通りの機能が同じペースで紹介されていると、全部を覚えなければいけないような気分になって進めるのが億劫になってしまいます。

ですが、この本では使用頻度が少ない、実際の業務ではこういう風に書くことが多い、などという風に説明されているので、読む時に「この書き方はあまり使われないみたいだから写経して動いて納得出来たら次に進もう。」みたいな感じで進めることが出来ました。

知ってはいるし使い方もなんとなくわかるみたいな分野を体系的に学ぶことが出来る

ハッシュ、シンボル、正規表現、繰り返し処理等、Rubyを使ってコーディングをする上で避けては通れないものです。

業務でRubyを書いているので、最低限使えているつもりでしたが、一通り写経して解説を読み、例題としてプログラムを書いていると今までのコードの反省点がいくつも浮かんできました。

特にたくさんのページが割かれていた配列やクラス等、使用頻度が高いオブジェクトに関する体系的な知識は実際のコーディングにすぐに反映されるのではないかなと思います。

テスト駆動開発を体験出来た。

独特な書き方(DSL)のRSpecではなくMinitestというフレームワークを使ってテストコードを書いてから、実際のコードを書き始めます。

Minitestはテストコードを書いた経験がなかった自分でも簡単に感じ、なおかつテストコードの便利さも実感出来るものでした。

業務やプライベートではRailsで開発をしているのでRailsでModelに書く処理にテストコードを書く時はどのように書くのだろうという疑問は残りましたが、これはいずれ自分で学習することにします。

話は逸れますが伊藤さんはRSpecの本の翻訳もされていたそうなので、自分がSwiftのアプリ開発を終える頃に最近のバージョンに合わせた新版を出してくれないかなあと期待しています。

読み終えた後

一度写経して読んだからといって全てを覚えられるはずがないので、配列を使ったコードを書く時にさっと読み直したりということが既に何度かあります。

一度やっただけあってどのあたりに目的の処理が書いてあるか検討が付くので、Rubyを書く時には机の上に置いたままになりそうです…。

当面はこの本やレファレンスを適宜参照しながら今まで書いてきたコードのリファクタリングをしたり、趣味で開発しているRailsのアプリケーションのコードを書きながらRubyに繰り返し触れることで、学習を進めていこうかなと考えています。

おまけ:発売後すぐに学習を始めて良かったこと

SwiftとそのIDEXcodeのアップデート直後に業務で学習と開発をスタートした時に感じた辛さなのですが、本に書かれているコードがバージョンの違いで動かないということが何度もありました。

書かれている内容自体の理解に努めたいのにそれ以前の所で詰まってしまうのは結構なストレスでした。

これはこの本特有の良いところではありませんが、Rubyで現在業務で使っているバージョンで解説もされているのは非常に助かりました。

オライリーのReal World HTTPという書籍を読み終えた。

現在業務で位置情報を利用したWebベースのアプリケーションを製作しているので今Webの基本的な知識を少しずつ深める良い機会だと考え、「Real HTTP World」を読んでみることにした。

どんな内容か

HTTP周辺の知識、なぜHTTPが現在のような形になっているのかを、歴史的な変遷とその仕様を解説しながら解説していく内容。GoでHTTPのそれぞれの規格のクライアントを実装していく章があるがそこをやらなくても読み進められる。

Scrapboxをつかった読書メモ

今ハマっているScrapboxを使って読書メモを残した。個人的な感想をアイコンを使ったコメント風の記述で、読んでいる最中に前提になる知識が不足していた場合やもっと掘り下げていきたいと思った時のログを残したので後から読み返して楽しい。

scrapbox.io

自分にとってのScrapboxとEvernote、それぞれの長所と短所

サービス開始当初から使ってきたEvernote

evernote.com

日本でローンチした2010年からずっとお世話になったEvernote。学生時代からの勉強や読書の記録。Webクリップ、レシピまで何でも突っこんで毎日利用していた。プログラマになってからは言語やフレームワークといったざっくりとした分類の仕方で参考になったドキュメントをどんどんクリップしていた。他のサービスを使ってみるか検討する時もまずEvernoteとの連携がデフォルトで出来るか、またはカスタマイズすれば出来るかというのが前提条件だった。 けれどプログラマとして働き始めてから毎日の開発、勉強の中でログとしてハマったところ、参考になったサイト、どういうきっかけで解決したか、解決出来ずに聞くしかなかったのはどこがわからなかったからか等をEmacsGoogle Drive上にmdファイルで貯めこんでいきはじめた。そのころからEvernoteをあまり使わなくなった。あまり使わなくなってからEvernote以外の選択肢も考えるようになってドキュメント管理ツールを色々と試した。社内のドキュメント共有管理ツールを探してたのも理由の一つ。

Evernoteの良いところと悪いところ

あくまで個人的な感想。

良いところ

  • とりあえずEvernoteに入れたから大丈夫、という状況を作れる。
  • 手軽にクリップ出来る。
  • サイト元が消えてもクリップしていれば見返せる。下世話な話題やエロいのはよく消えるから大事。神。
  • ざっくりとしたスタック、ノートブックのわけかたでも検索したら引っ掛かる。
  • 画像やPDFの文字も検索出来る。神。自分の書いたメモをスキャンすればあとで検索して見つけられる。神。
  • サードのサービスを使えばmarkdownも対応可能。
  • 情報が豊富。コミュニティも親切で活発

(自分にとって)悪いところ。特にEvernoteを使う必要ないなと感じたこと。

  • 重い。
  • 前職からプログラマに転職してから勉強と仕事で手一杯 + 楽しいので下世話な話題やネットで今日話題の~みたいなのに関心がなくなった。
  • エロはDMMで良くない?ってなった。そうじゃないものに関しては一期一会の精神で。
  • ざっくりとした階層の管理をしているのに面倒臭く感じる。→ 管理しても恩恵が少ないからやる気にならない? or 検索すれば良いから?
  • 「あとで整理する」みたいなフォルダが出来る。結局整理しない。自分の性格を鑑みて当然起こるものと想定しておくべきだった。
  • そもそもクリップしたものを見返さない。プログラミングのことに関しては検索して解決してしまうのでEvernoteの中に入れたな、という考えに至らない。
  • 画像やPDFを入れない。
  • 自分の書いたメモをスキャンしても汚すぎて認識しない。
  • markdownのためにサードのアプリケーションやサービスと本家を使い分けるのしんどい。

悪いところはほぼ自分の性格が原因になっているので、一部を除いてEvernoteに非はない。Evernoteが便利で離れられない人がたくさんいるのも納得。

Scrapboxの良いところと悪いところ

scrapbox.io

開発中のログとかはプライベートのプロジェクトを作って完全に移行済み。その他のドキュメントは少しずつ移行しながら利用中。

良いところ

  • 独自の記法が個人的な用途に関してmarkdownより便利で書きやすく、後から見易い。
  • リンクを作ることでドキュメント同士を関連付けられる。あるテーマについて掘り下げたらそれに関する情報が集まる。
  • リンクによって階層で管理する必要がない。リンクを作るだけで良い。
  • 掘り下げた話題、今学習中の言語についてのドキュメントが繋がって楽しい。
  • 関連付けられたテーマについて調べたことを残すのが楽。後から見返すのも楽なので見返す頻度が上がる。
  • コミュニティが大きくなってきている。親切。
  • これから連携やサードパーティが盛りあがっていくかも。
  • 一部部分のクリップならブックマークレットから可能。

(自分にとって)悪いところ。

  • Webベースのみ。公式のMacアプリやiOSアプリはない。iOSアプリは欲しい。
  • 大きくなってきているが今のところEvernote程ではない。
  • たまに記法間違える。
  • markdownに変換するブックマークレットがあるものの、Scrapboxから変換してきました感MAX。

EvernoteからScrapboxへ移行中

自分の用途が

  • 開発、学習中に残すドキュメント
  • 読書メモ
  • ちょっとしたクリップ ぐらいで充分なことに今さら気付いたので移行後も不満なくScrapboxを利用出来ている。Evernoteから他のサービスに移行しようかなと考えている人はぜひScrapboxを一度使ってみてください。

せっかくプログラマになったので勉強してScrapboxみたいな気に入ったサービスに何かしらの貢献が出来るようになりたいなぁ、とぼやいて終わり。

Swift初学者のSwift学習ログ(書籍:本気ではじめるiPhoneアプリ作り)

形式

基本的に詰まった順に列挙。

xcode最新版(9.0)と参考書で使用されているバージョン(8系)との違い

githubと連携させないので業務では必要ない。 必要なら以下参照 Xcodeの概要: ソースコード管理機能を使う

editorのdocument outlineが見当たらない

項目によってあったりなかったりするだけだった。 ただ、メニューバーにあったshow document outlineは項目が消えていた。

実機接続のテストでiPhoneの設定からプロファイルとデバイス管理がない

プロファイルのみになっている。

xcodeで実機の利用ができない(0xE80000E2) - Qiita

Xcode9で実機でのアプリが実行できないとき

を参考に解決。

Optional型の変数を定義した後にアンラップ処理後の変数を利用しない場合の表現がある理由。

厳格なSwiftに対して返り値がなくても問題ないということを宣言するため。

どこよりも分かりやすいSwiftの"?"と"!" - Qiita

enum型が初見でしっくりこなかった

列挙型

// enumの定義
enum Fluit {
  case Apple
  case Orange
}

// Switch文の値にenum値を指定するとenumの値がすべて網羅されているかチェックが入る。処理の記述漏れ対策に良い。
let value = Fluit.Orange
switch value {
case .Apple:
    print("Appleです")
case .Orange:
    print("Orangeです")
}

Clusure、無名関数について

意味のわからないかたまりに見えた。

{(引数:引数の型) -> (戻り値の型) in
    // 処理
    return 戻り値
}

こんなの。Rubyでの記法のProcやラムダと比較しながら理解した。

Swift さくっと確認したい基礎文法 [クロージャ(closure)] - Qiita

特徴と考え方を理解

エラーが起きた箇所を表示させたい

エラーの画面が意味不明。 thread logのみが表示され見辛い。

何かしらの設定を弄ってしまった可能性あり

// Xcodeの設定(カラースキームとかプロジェクトとか)がリセットされるので注意。 defaults delete com.apple.dt.Xcode.LSSharedFileList defaults delete com.apple.dt.Xcode

をターミナルで実行して解決

同じ症状の人 xcode - Thread 1: Stopped at breakpoint 1 - Stack Overflow

Xcodeでコード補完が効かなくなった時に… - Qiita

Auto LayoutのUpdateFramesがadd New Constratintsにない

同じ所にボタンとしてupdateframesがある。 ただクリックできない items of new constraintsを設定出来ないがそれは大丈夫なのか

Type 'ViewController' does not conform to protocol 'UITableViewDataSource'が解決出来ない。

// テーブルの行数を返却する
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            // Todoの配列の長さを返却する
            return todoList.count
        }
        
        // テーブルの行ごとのセルを返却する
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            // Storyboardで指定したtodoCell識別子を利用して再利用可能なセルを取得する
            let cell = tableView.dequeueReusableCell(withIdentifier: "todoCell", for: indexPath)
            // 行番号に会ったToDoのタイトルを取得
            let todoTitle = todoList[indexPath.row]
            // セルのラベルにToDoのタイトルをセット
            cell.textLabel?.text = todoTitle
            return cell
        }

2つのメソッドがボタン押した時のメソッドに入っていたのが問題だった。

Storyboardの制約を使いこなせない

Scrapboxに書いた。 scrapbox.io

参考 StoryboardのAutolayoutの基本 iOSのAuto Layout - Qiita