プログラミングに関する情報を英語でググるときのコツ
あけましておめでとうございます!今年も本ブログをよろしくお願い致しやす🙏
さて、私はプログラミングに関する情報を調べる際、基本的に英語でググるようにしています。理由は単純で、英語のほうが圧倒的に情報量が多いからです。このエントリではいつも私が英語でググる際に使っているキーワードなどをメモしておきます。
- 実装した機能がうまく動かない場合
- 〜が表示されない
- メソッドなどが呼ばれない/実行されない
- プログラムで〜したい
- 2つの違いを知りたい
- 〜かどうかをチェックしたい
- 〜を検知したい
- 〜の実装方法を知りたい
- 〜についての最良の方法を知りたい
- あわせて読みたい
実装した機能がうまく動かない場合
〜 not work
でググります。「動く」だからといって move で検索しても期待した検索結果にはなりません。
さらにOSバージョン等を指定する際は
〜 not work in iOS 12
のように指定するとヒット率が上がります。*1
〜が表示されない
〜 not show (up)
メソッドなどが呼ばれない/実行されない
〜 not called
〜 not execute
プログラムで〜したい
programmatically
というキーワードを使う。
例えばiOSの開発で「Autolayoutの制約(constraints)をStoryboardからではなくプログラムコードで追加したい」場合は
autolayout constraints programmatically
なんかでググるとそれっぽいのがヒットする。
2つの違いを知りたい
日本でもよく使う vs
というキーワードが便利。
例えば REST における PUT と POST の違いについて知りたい場合は
PUT vs POST
のようにググるとそれっぽいのがヒットする。または普通に
difference PUT POST
のようにググるのも良い。
〜かどうかをチェックしたい
普通に check
というキーワードが使える。例えばある文字列が〜を含んでいるかどうかをチェックする方法を知りたい場合は
check if string contains 〜
のようにググってやるといい感じにヒットする。
〜を検知したい
例えば通信が切断されたタイミングを検知する方法を知りたい場合は
how to detect disconnection
のようにググると良い。
ユーザーが使用している OS のバージョンを検知する方法も
how to detect user os version
のようにググるとそれっぽいのがヒットする。
〜の実装方法を知りたい
How can I implement 〜
〜についての最良の方法を知りたい
best practices for 〜
あわせて読みたい
2018年を振り返る
このエントリは、今年一年の自己の振り返り Advent Calendar 2018 - Adventar の記事です。
どうも、koogawa です。今年も残りわずかですね。
今年のはじめに目標を立てていたので、ひとつずつ振り返ってみたいと思います。
目標振り返り
1. Stack Overflowで5000 reputationを目指す
達成しました🎉
実を言うと5月の時点ではまだ 4,000 reputation 程度でした。
今年の目標は 5,000 reputation なんだけど、今のままだとちょっとキツいかもしれん(;´ω`)
— Og🌗エンジニア🏝宮崎 (@koogawa) 2018年5月26日
しかし後半になると怒涛の追い上げを見せ、終わってみれば10月には目標の 5,000 に達していました。人間、追い込まれるとなんとかなるもんですな。
この調子で次は 10,000 reputation 目指します💪
2. 公開しているOSSのメンテナンスを続けていく
いくつかオープンソースのライブラリを公開していますが、しっかりメンテナンスも続けております。
- GitHub - koogawa/FoursquareAPIClient: Very simple Swift library for Foursquare API v2 - Foursquare API 用の軽量クライアント。公式デベロッパーサイトでも紹介されている
- GitHub - koogawa/LocationPickerController: Simple location picker with a built in maps. - 地図から緯度経度を取得できるUIライブラリ
- GitHub - koogawa/iSensorSwift: Sense a lot of things. (Swift ver) - 位置情報や輝度、音、速度など、iOSで検知できる機能を集めたSampler
今年公開された Swift 4.2 にももちろん対しております。
何れもニッチなライブラリですが、ちょっとでも使ってくれる人がいる限りメンテナンスは続けていきたいと思っています。
3. リモートでも参加できる勉強会に参加する
リモート・オフライン問わずいろんな勉強会に参加しました。
- PHPカンファレンス福岡2018
- iOSDC Japan 2018 前夜祭に参加してきたよ #iosdc - koogawa blog
- PHPカンファレンス福岡 2018 #phpconfuk に参加してきたよ - koogawa blog
- 宮崎 × 沖縄 JSやらNight! - connpass
- Webナイト宮崎 Vol.1 ~てげWeb学びたい~ ※10/9参加枠15→30名に増加 - connpass
昨年はまだ子供が小さかったこともあり、iOSDC への参加は見送っていたのですが、今年は一年ぶりに参加できました!楽しかったー😆
子育てとバランスを取りつつ、来年も可能な限りイベントに参加していく所存です。
おまけ
その他、今年あったイベントをちょっとだけ
息子が2歳に
移住当時は0歳だった息子が先日2歳になりました👦
宮崎の自然に囲まれ、 元気に育っております。
副業から本業へ
東京から宮崎へ移住後、しばらく宮崎を本拠地とする企業に正社員として勤めていたのですが、今年10月に退職しました。
退職理由としては、今年の夏ぐらいから初めた副業*1の方が楽しくなってしまったというのが正直な理由です。今はその副業が本業になっており、よりエキサイティングな毎日を送っております。
また、地元の会社文化に適応できなかったというのも理由の一つです。詳しい内容については割愛しますが、やはり地方には地方独特の文化や仕事の進め方があることを肌で感じました。もし地方への移住に興味があり、詳しい話を聞いてみたい方がおりましたら適当に声をかけてください。
◆
そんなわけで、来年もどうぞよろしくお願い致します!
*1:東京の案件です
【iOS/Swift】Firebase Cloud Firestoreで簡単なGPSロガーを作ってみる
この記事は Firebase #2 Advent Calendar 2018 4日目の記事です。
Firebase を理解するには何か作ってみるのが一番!ってことで、今回は簡単なGPSロガーを作ってみました。
次のような機能があります。
- Startボタンを押すと位置情報を記録開始
- アプリをバックグラウンドに落としても記録し続ける
- 位置情報が取得されると地図にもピンが立つ
- 1日経過したデータは起動時に自動削除
- Stopボタンを押すと位置情報の取得終了
***
以下、実装メモです。すべての実装は説明できないので、完全なソースコードは最後の方に貼ってある GitHub リポジトリを参照してください。また、今回は学習を目的としたサンプルプログラムという位置付けなので、料金については詳しく触れません。Cloud Firestore はデータの読み取り、書き込み、削除の回数によっても課金されますので、下記のリンクもよくお読みください。
Cloud Firestore の料金 | Firebase
動作環境
- Xcode 10.1
- Swift 4.2
- FirebaseCore 5.1.8
- Firebase/Firestore 5.13.0
- CocoaPods 1.5.3
手順
プロジェクト作成
https://console.firebase.google.com/ から新規プロジェクトを作成します。
チェック項目については各自おまかせします。
テータベースの作成
左のメニューから「Database」を選択し、「データベースの作成」ボタンをクリックします。
Cloud Firestore データモデルについて
公式ドキュメントから引用します。
Cloud Firestore は NoSQL ドキュメント指向データベースです。SQL データベースとは違い、テーブルや行はありません。代わりに、データは「ドキュメント」に格納し、それが「コレクション」にまとめられます。
これは図に表すと理解しやすいと思います。
また、各「ドキュメント」には、一連のキーと値のペア(フィールド)が含まれています。今回は locations
コレクションにGPSログ(ドキュメント)を追加していく想定で進めていきます。
iOSアプリに Firebase 追加
「iOS」ボタンをクリックします。
バンドル名は com.example.GPSLogger
、アプリ名は GPSLogger
としました。
GoogleService-Info.plist をプロジェクトに追加
画面に従っていくと GoogleService-Info.plist
をダウンロードするように促されるので、これをプロジェクトに追加します。
このファイルには Firebase を使うためのIDなどがセットされています。このファイルを追加しないとアプリ起動時にクラッシュします。
Cloud Firestore インストール
次のような Podfile を用意して pod install
します。
use_frameworks! target 'GPSLogger' do pod 'Firebase/Core' pod 'Firebase/Firestore' end
アプリで Firebase を初期化する
AppDelegate で FirebaseApp.configure()
を実行し、アプリを初期化します。
import UIKit import Firebase @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { FirebaseApp.configure() return true } }
モデル作成
位置情報を格納するためのモデルを作ります。緯度、経度、作成日時のみを保持するようにしました。
struct Location { let latitude: Double let longitude: Double let createdAt: Date init(document: [String: Any]) { latitude = document["latitude"] as? Double ?? 0 longitude = document["longitude"] as? Double ?? 0 createdAt = document["createdAt"] as? Date ?? Date() } }
緯度経度を格納するための型(地理的座標)も用意されていますが、今回はわかりやすくするためにあえて Double
型を採用しています。
後述しますが、Firebase からはデータが Dictionary
型で返ってくるので、init(document: [String: Any]) {
のようなメソッドを定義し、そこから Location
インスタンスを生成できるようにしています。
Firebase では次の型が使用できます:配列、ブール型、バイト、日時、浮動小数点数、地理的座標、整数、マップ、Null、参照、テキスト文字列。
Startボタンを押したときの処理
位置情報の取得を開始します。*1
self.locationManager.startUpdatingLocation()
位置情報を追加
取得できた位置情報(CLLocation
)を Firestore に追加します。
let db = Firestore.firestore() var ref: DocumentReference? = nil ref = db.collection(kLocationsCollectionName).addDocument(data: [ "latitude": location.coordinate.latitude, "longitude": location.coordinate.longitude, "createdAt": FieldValue.serverTimestamp() ]) { err in if let err = err { print("Error adding document: \(err)") } else { print("Document added with ID: \(ref!.documentID)") } }
追加日時は FieldValue.serverTimestamp()
メソッドで時間軸を全てサーバーに預けてしまうことによってモバイルの個体差によるずれを解消しています。
リアルタイムアップデート
addSnapshotListener
メソッドを使用すると、ドキュメントが更新されたときにイベントを受け取ることができます。
let db = Firestore.firestore() self.listener = db.collection("locations") .addSnapshotListener(includeMetadataChanges: true) { [weak self] documentSnapshot, error in guard let document = documentSnapshot else { print("Error fetching document: \(error!)") return } print("Current data: \(document.description)") self?.loadStoredLocations() }
ここではイベントを受け取るたび(つまり位置情報が追加されるたび)にデータをロードし、テーブルビューを更新しています。includeMetadataChanges
を true
にしているのは、データが削除された際にもイベントを受け取るためです。
Stopボタンを押したときの処理
位置情報の取得を停止します。
self.locationManager.stopUpdatingLocation()
また、リアルタイムアップデートも停止します。先ほど実行した addSnapshotListener
メソッドの戻り値 ListenerRegistration
の remove
メソッドを呼ぶことで、イベントの受け取りを停止します。
self.listener.remove()
アプリを起動したときの処理
getDocuments
メソッドを実行して Firestore に保存されている位置情報をロードします。
let db = Firestore.firestore() db.collection(”locations”) .order(by: "createdAt", descending: false) .getDocuments { [weak self] snapshot, error in if let error = error { print("Error getting documents: \(error)") } else { self?.locations = snapshot?.documents.map { Location(document: $0.data()) } ?? [] } }
createdAt
でソートをかけて全データを取得し、Location
型の配列としてローカルに持ちます。
古いデータの削除
古いデータがいつまでも残ってしまうのを防ぐため、1日経過した位置情報ログを削除します。
まずは whereField
を利用して1日(86400秒)より古いデータを抽出します。
let db = Firestore.firestore() db.collection("locations") .whereField("createdAt", isLessThanOrEqualTo: Date().addingTimeInterval(-86400)) .getDocuments { snapshot, error in if let error = error { print("Error getting documents: \(error)") return } for document in snapshot?.documents ?? [] { print("Deleting document", document) self.delete(documentID: document.documentID) } }
そして一件ずつ delete
メソッドで削除していきます。
fileprivate func delete(documentID: String) { let db = Firestore.firestore() db.collection("locations") .document(documentID) .delete() { err in if let err = err { print("Error removing document: \(err)") } else { print("Document successfully removed!") } } }
大量にデータを削除する場合はメモリ不足エラーを避けるため、小さなバッチに分けてドキュメントを削除することが推奨されています。
所感
割と簡単にGPSロガーが作れてしまいました。ドキュメントが充実しているのも安心できますね。
とくに便利なのがオフラインデータ機能です。この機能により、アプリが使用している Cloud Firestore データのコピーがキャッシュに保存されるため、端末がオフラインの場合でもアプリはデータにアクセスできます。端末がオンラインに戻ると、アプリがローカルで行った変更とリモートの Cloud Firestore に保存されたデータが同期されます。なんて素敵な機能なんでしょう!
ソースコード
こちらに全てアップしてあります。Firebase を使い慣れている方にとってはツッコミどころ満載だと思いますので、ご指摘など歓迎です:-)
リンク
- Cloud Firestore | Firebase Documentation - 公式ドキュメント
Xcode で Breakpoint を一括で削除する方法
割と知らない方が多かったのでメモ。
- 左のペインに Breakpoint Navigator を表示
- Workspace 右クリックして「Delete Breakpoints」選択
- これですべての Breakpoint が消える
頂いたフィードバック🙏
Breakpointエクスプローラを選択したまま cmd + a → delete でも消せる https://t.co/VJwIo5igCl
— もちゅる|リモートパパエンジニア (@mothule) 2018年11月1日
近況
こんにちは koogawa です。たまには近況報告なんかを書いてみます。
宮崎におります
普段からTwitterで宮崎のことをツイートをしまくってるので今さら感はありますが、「自然の多いところで子育てをしたい」という夢を叶えるために昨年、東京から宮崎に移住しました。
長い電車通勤生活からも開放され、今は自転車・車中心の生活にシフトしております。
東京の1Kぐらいの家賃で戸建てが借りられるのも魅力のひとつである。駐車場も数台分付いてくる
— Og🌗エンジニア🏝宮崎 (@koogawa) 2018年9月9日
そんなわけで、現在は戸建ての物件を借りてのんびり暮らしております。騒音を気にしなくてよい、というのは良いことですね。
会社員 兼 個人事業主
今年の5月に Marimosoft という屋号を取得し、個人事業主になりました。
とは言っても完全な自由業というわけではなく、昼間は本業に集中し、夜は副業としてコードを書くというスタイルを取っています。睡眠時間を削る必要があるため、昼間は若干眠いですが、なんとか両立しています。
最近のお仕事
まだ詳しくは書けないのですが、わりと大きめのプロジェクトをお手伝いさせていただいております。自分はiOSをメインで担当しておりますが、非常に強いメンバーが集っており、刺激の多い日々を送っております💪早く公開したいな〜
副業の難しさ
会社員 兼 個人事業主として副業をやってますが、割とツラい面もあります。
日中は副業できない辛み
本業があるため、副業先で日中開催されるMTGに参加することが難しかったり、Slackに飛んできたリプライへの回答が遅れたりと、メンバーの皆さんにはいろいろと迷惑をかけてしまっていると思います🙇🏻
ただ、ちゃんとMTGの議事録は残してもらえますし、本業の休み時間を利用してSlackに返信したりもできますので、今のところなんとか続けられております。
眠み😪
帰宅後は、子供をお風呂に入れ寝かしつける、というタスクがあるため、副業を開始できるのはどうしても22時以降になってしまいます。そこから作業を始めると、眠りにつけるのはどんなに早くても午前0時過ぎになります。時には朝5時頃まで頑張ることもありました。そのため、昼間(特にランチ後)はちょっと眠くなるので、コーヒー飲んで頑張ってました☕
まとめ
いろんな課題はありつつも、意外と何とかなるもんです。しかし、最近はさすがに体力的にもキツくなってきたので、近い内に本業か副業のどちらか一本に絞りたいと考えています。
追記:その後、副業一本に絞りました。 現在はフリーな感じでやらせていただいております。めちゃめちゃ楽しいです💪
【Stack Overflow活動記】reputationが5,000に!Tag Wiki 編集の承認権限が付与されました
Stack Overflow活動中 の koogawa です、こんにちは。
昨日ついに reputation(Stack Overflowにおける信頼度)が 5,000 に到達しました🎉
今年の初めに設定した目標 が「Stack Overflowで5000 reputationを目指す」だったので、無事達成できたことになります。
ちなみに、エンジニアアウトプットランキング Stargzr によると、日本で reputation 5,000 以上のユーザーは現在3人しかいないようです *1。ちなみに、1位の id:KishikawaKatsumi さんは 8,000 reputation を超えていらっしゃるので本当にすごいですね!
そして、同時に Approve Tag Wiki Edits 権限が付与されました。これは Tag Wiki の編集申請を承認できる権限になります。
Tag Wiki とは
Stack Overflow で質問する際には ios
, swift
, xcode
などの Tag を設定することができます。
各々の Tag には専用のページが用意されており、Tag の概要文やその Tag における上位回答ユーザー、最近のベストな回答などが掲載されます。
すべてのユーザーは Tag 概要文を編集することができますが、Approve Tag Wiki Edits 権限(今回私に付与された権限)を持つユーザーに承認されるまでサイトには反映されません。
Tag Wiki 編集が承認されるとどうなるか
初めて編集が承認されたユーザーは「Tag Editor」バッジ(銅)を獲得できます。
さらに、50回編集が承認されると「Research Assistant」バッジ(銀)を獲得できます!
次なる目標
次は 10,000 reputation で付与される Access To Moderator Tools 権限獲得を目指します💪
私の Stack Overflow 活動はこれからも続きますよ!
*1:もちろん実際はもっといるんでしょうけどね
iOSDC Japan 2018 前夜祭に参加してきたよ #iosdc
飛行機、電車を乗り継ぎ、iOSDC Japan 2018会場へ!2年ぶりの参加です。
ここは WWDC か!と思いました。
ビールもたくさんデプロイされていました。途中、ビールが足りなくなるというハプニングもありましたが、スタッフさんが近くのコンビニなどで補充してくれました。感謝しかない🙏
前夜祭では次のトークを聴講しました。
- 標準アプリから学ぶ、HIGが教えてくれないiOSデザインのこと
- キラリと光るテクニック、アプリをデモするときの心構え
- iOSエンジニアの為のgrpc-swift入門
- 再利用可能なUI Componentsを利用したアプリ開発
- ツールとして利用するUIテスト
- 設計時空のリファクタリング〜複数アーキテクチャを抱えたアプリのリファクタリング事例〜
ひとつだけピックアップするとRyo Usamiさんの「標準アプリから学ぶ、HIGが教えてくれないiOSデザインのこと」がとても印象に残りました。
- 広く利用されるものを利用する
- 同じ見た目のものは場所が違えど同じふるまいをしよう
- 新しい標準が登場したときはその背景、使い方を知ろう
という内容が一貫しており、みんな日常的に使っている「ドア」の例えが非常にしっくりきました。
「ドア」の使い方をあまり意識しないのは何度も使ってるからであり、「ドア」であれば同じふるまい・利用のされ方をするからである。そこに突然「同じドアなのに同じ動きをしない」ドアが現れると人は戸惑う、と。
***
ノベルティもたくさんいただきました!
#iosdc 前夜祭での戦利品です pic.twitter.com/eT3sUoO2ib
— Og🌗エンジニア🏝宮崎 (@koogawa) 2018年8月31日
今日も楽しんでいきます!