新年の挨拶と1年半ぶりにiOSアプリをバージョンアップした話
あけましておめでとうございます。コミケを見にきていただいた方はお疲れ様でした。
突然だがニコニコ実況っていうサービスが好きだ。日曜洋画劇場をニコニコ実況片手にみんなで見てる気分になるのが好きだった(最近は全く見なくなってしまった。理由は察してくれ)。ニコニコ実況っていうのは要はテレビ版のニコニコだ。俺の部屋のテレビとPCはそっぽ向くように置かれてるのでテレビ見てる時にパソコンを見るのが面倒だった。なのでiPhone版アプリを作った。
12月後半、あるきっかけで休日の3連休にがっつり改修を行い、iTunes Connectのホリデーが終わってすぐアプリ申請、大晦日にリリースされた。iPadで文字が小さくなってしまう問題があったりもしたが(修正版を申請したのでもう少しお待ちください)、概ねレビューを見ると好評のようでアップデート作業をやってよかったなと思っている。
最後に更新してから1年半以上経ったアップデートになったわけだが、最初はリファクタリングのつもりだったんだがこれから書く変更点のせいで結局ほとんど1から書き直すことになった。この文章を書く前は「こうしたほうがいい」とかいう話にしようかなとおもったんだけど正月だしお酒飲んでてめんどくさくなってきたのでただの列挙になってしまった。ここまで読んでる人がいたら申し訳ない。
覚えてる大きな変更点
ARC
それまでのアプリは非ARCコードで書かれていたので、ARC対応にした(アップデート前はiOS 4.3対応だったため)。retain
, release
, autorelease
, dealloc
書かなくてよくなったのはほんとうに有難い。やはり面倒なことは一つでも少ない方がいい。行も短くなるし。
CocoaPods
以前は対応しているライブラリも少なく使ってなかったのだが、最近はかなり揃っているので使うことにした。使っているライブラリは次の通り。
- AFNetworking
- CocoaLumberjack
- AFKissXMLRequestOperation
- SSKeychain
空っぽなプロジェクトにAFNetworkingを追加すると、出来上がるバイナリサイズが370KBほど増えたので結構怖いなと感じた。何でもかんでも追加するとファイルサイズがどんどんでかくなっていくので使用するライブラリは必要最小限にするようにしたほうがいい。
今はMac / iOSのアプリを一つのxcworkspaceで作ってるんだが、そういったPodfileの定義する方法の情報が見つからなくて辛かった。ごちゃごちゃいじってたらできたんだが、ここでは書かない。興味ある人はそのアプリをOSSで公開する予定なのでそれを待ってほしい。
Storyboard
チーム開発ではコンフリクト解消が困難になるので使わないほうがいいだろうが、個人開発では使ったほうがいいと思う。ビュー間の移動をSegueでコード無しで追加できるのは楽だ。ただiPadのビューが6つあるとThunderbolt Displayを使っていてもStoryboardの編集は狭くて使いづらいのである程度ビューが少ないアプリじゃないときついかもしれない。
あと慣れてないのも悪いんだが、Auto layoutにかなり苦しめられた。親画面からの相対位置で右寄せ、下寄せさせたいだけなのに何度もXcodeに怒られながら修正をする必要があった。たまに警告なしの状態にしてもビルド時に失敗したことがあったので、なんかバグが残ってる気がする。前のバネで指定する方式は楽だったなあ。
Localize
前はUIのローカライズをするときにはxibをロケールの数作って編集していた気がするんだが、今はxib/storyboardとstringsファイルに分けて後者だけを編集すればいいようになっている。便利だなと思う一方で、自動生成されるstringsをみてもどの位置の文字列かパッとわからないこともあって辛かった。今後xib/storyboardいじったときにstringsのアップデートで苦しめられそうな未来が予想できる。
あと前もあったんだが、Localizable.stringsを追加してもシミュレータでは追加が反映されるのに実機では反映されないことが起きた。Option押しながらクリーンをやったら反映されるようになったんだが、原因がはっきりせずにもやもやしたままだったりする。
iOS 7の全画面ビュー
iOS 7からステータスバーの裏もビューとして使われるようになった。そのためコメントが流れる領域とステータスバーが被ってしまい、ステータスバーがとても読みにくくなった。ぐぐると一枚ビューを置いてTop Layout Guideを使ってステータスバー分だけずらすように設定しておけばStoryboardだけでもステータスバーには被らないように出来た。
delegateからBlocksへ
今回のアプリだと例えば「HTTP API叩いて通信結果が成功したらビューを更新して失敗したらエラーダイアログだす」みたいな処理が多い。今までまずは成功、失敗呼び出しを定義したプロトコルを作り、delegateを登録し、ってことをやってたんだがこれをBlocks型に書き換えた。 Blocksにしたことで「成功と失敗処理が同一メソッド内にあるので見やすい」「プロトコルを定義する必要がない・名前を考える必要がない」という楽さを感じた。ちょっと変わったことをやろうとすると苦労することもあるが(例えばBlocksで再帰呼び出しをメモリリークしないように書く、とか)、ちょっとした通信処理とか書くときにはスッキリ書けるっていうだけでBlocksに変えてよかったなと思う。
終わりに
1年半ぶりのアップデートをやることでiOSの世界では1年半ってとても長いんだなというのを強く感じた。例えばNSArray, NSDictionaryなどのシンプルな糖衣構文や、上では書いてないがModulesも使うようになった。OSのメジャーバージョンも上がるのが早いし、開発者が追いついていくのもなかなか大変なものだ。それでも、いやだからこそiOSは新しいものが好きな開発者にとって楽しいプラットフォームなのかなと思ったのだった。
冬コミ 3日目 12/31 (Tue)に「ななかINSIDE PRESS vol.4」を出します(西し-35a)
冬だ!スノボだ!コミックマーケットだ!
夏コミの追い込みもいつのやら。早いもので冬コミの入稿が終わりました。今回で4回目のコミケ出展でございます。今年はもしかしたら会場には行けないかもしれないのですががが。
今回も記事8本、108ページとよくわからない分厚さになっております。メインテーマは「Chef!」ということで表紙もChefをイメージした女の子になっております(表紙は@ok__rayさんに描いてもらいました)。Chefでサーバを構築してみたはいいものの途中からめんどくさくなって手作業で設定してる人いませんか、後ろから包丁でXXXされちゃいますよ!(そんな設定はない)
内容も以前のようにプログラミング話ばかりではなく、幅広く取り上げております。詳細は第7開発セクションのサイトをどうぞ!
さて、今年の夏コミの紹介を書いた時のように今回も各記事の簡単な紹介をしますので、なんとなく読んだ気になってください。
各記事の紹介
(特集記事) わがままChefのおいしいrecipeの作り方 @gujauja & @suzuki_kenta
- 業務で実際にChefを使っている2人によるChefの入門記事です。数時間Chefを触っただけの私が理解に難しいなと思ったところには(強引に)解説を入れてもらっているのでつまづきにくい入門記事になっていればと思います。後半ではChef Solo + Knife Soloでユーザ作成、インストール、(パッケージとコマンドによるものの2種類)、ファイル作成、ロギングを行います。
DMM 3Dプリントで連装砲ちゃんを作る @Omegamega
- DMM 3Dプリントで自分でモデリングした連装砲ちゃん(ぜかましのそばにいるやつ)を作ってみたレポート。素材は石膏、ナイロン、アクリルの3つがあるんですね。失敗できない(いっこつくるのに3,000円とかかかる)のは怖いけど、専用の工具と膨大な時間を使わないと作れなかった3Dモデルの実体化ができるなんていい時代になったものです(※特許切れという意味で)。@Omegamegaのブログに写真や動画があるのでそちらもどうぞ。
MMDAI2/VPVM on Qt 開発戦記 @shimacpyon
525円とNexus7で"Oculus Rifts7" @binzume
- Oculus Riftというのはヘッドマウントディスプレイの一つなんですが、ジャイロが入ってるので首を傾ければ向いた方の映像が見えるってやつで、3DCGと組み合わせるとその世界にいるような感覚を体感できます(どれくらいやばいかはhttp://www.youtube.com/watch?v=GoQ0OXJCbaEこの動画を見ていただければわかるかと)。この記事ではジャイロ搭載のNexus 7を使うことでコードレスでHD画質のOculus Rift(みたいなもの)を作ってみたそうです。私も実際に見てみたんですが視界が追随してくるのはまじでヤバイです。
Blink(1)でウキウキウォッチング @tboffice
- Kickstarterから生まれた様々な色にひかるUSBデバイス「blink(1)」を何を間違えたのか10個も買ってしまったために何が何でも役立ててやろうとした人の記事です。1bitでは表現できないものということで、トイレの個室ごとの空き状態を表示したりしています。Blink(1)がそこまで強い光量を持ってるわけではないので、新着イベントよりも状態表示のほうが向いてそうです。
今から始めるMySQL Cluster入門 @kukishuzo
大炎上!在席監視 iBeacon @saiten
某リンゴの倒し方?俺知ってるよ! @inokinn
- この記事は自分の目で確認しよう!
ということで、12月31日、西し-35aでお待ちしております
一冊800円です。既刊ももっていきますよー。
歌舞伎座.tech#1で「sbtのマルチモジュールのビルドおそくね?」というLTをしてきました
一行でまとめ:マルチモジュール形式のsbtプロジェクトの場合にSNAPSHOTバージョンのライブラリを使っていると毎回ライブラリの解決してて遅くなるからHTTP Proxyとか使ってキャッシュしましょう。
id:yuto_sasaki に発表資料を見てもらったあとで、SNAPSHOTバージョンが悪いんじゃね?という助言を頂きました。ありがとうございます。
開場中にid:xuwei から補足を頂いてました。ありがとうございます:
#kbkz_tech SNAPSHOTになってると毎回見に行くのは、そういう仕様。 offlineというKey https://t.co/w1FIHkuSzR とかあるけど。あとそもそも毎回cleanとかしない限り、そっちの遅さより、コンパイル時間のほうが問題な気がするけど
— Kenji Yoshida (@xuwei_k) 2013, 9月 25
コンパイル時間を早くしたいのはもちろんなのですが、それにはハイスペックマシンを用意するくらいしか(ry
C84の3日目に「ななかINSIDE PRESS vol.3」を出します(東ぺ-15a)
いよいよ今日から夏コミですね!なんだか気温がとても高くなりそうとのことで、参加者の方々はくれぐれも温度調節、水分補給を怠らず楽しく参加してきてくださいね。家に帰るまでがコミケです。
さて、私がコミケに出展側で参加するのもこれで3回目。前回、前々回に続いてプログラミングメインのよもやま話がどばどば詰まった「ななかINSIDE PRESS vol.3」を頒布します。 執筆者8人で128ページときりの良い数字になっております(お値段は600円ときりがよくありませんね)。かなり分厚い(背表紙の幅が1cmくらい?)ので近くを通られましたら、お手にとって確かめていただければと思います。 第7開発セクションのサイトにはサンプルページも用意してしますので興味がある方はそちらもご覧くださいませ。
本の内容
- AWS実践入門 -AWSの本当のところ @con_mame
- 業務でAWSを使用しているid:con_mameによる、使用時の注意ポイントや性能測定です。 Let's インスタンスガチャ (※有料です)!
- よりよい設計手法でSAN値を守る More Better Rails @rosylilly
- coffeescriptで作るcoffeebotで優雅なコーヒーブレイク @saiten
- 「それ名前駆動開発」だろって言ってしまうタイトルですが、中身はコーヒーメーカーにコーヒーが残っているかどうかを監視してくれるボットを作った話です。個人的に一番好きな記事です。
- Render Scriptでサクサク動くAndroidアプリを @binzume
- RenderScriptというのはアプリからネイティブコードを実行する仕組みです。それNDKでいいじゃん?と思うかもしれませんが、CPU非依存で書けるのでARM以外も対象とするときには楽ができるかも。
- できる!たのしい!週末iPhoneアプリ開発 @kenmaz
- 知識に差が出る!? Coureutils大全#2 @tboffice
- lsやcatといった日常生活に欠かせないコマンドたちのご紹介。こんなコマンドあるんだへー、とお手持ちのへぇボタンを押しながらパラパラ読むのが多分正しいかと。前号からの続きですが、これだけ読んでも問題ないです。
- Asteriskで作る個人認証システム @mtgto
- 私です。最近増えてきている「二段階認証」を個人でもやるための方法を音声電話、SMSの2つで書きました。
- 88888の多い動画は!? ニコニコ動画のデータを分析してみよう @shibacow
- 今年の5月に公開された830万件の動画のデータとコメントをHadoopを使って分析する方法の解説です。例としてコメントに「88888」が多いものを調べています。
ということで
8月12日(月)、東ぺ-15aでお待ちしております。私は朝頃サークルブースにいると思いますのでよろしくお願いします。既刊も持っていくよー。
DashでJava SE 7 日本語ドキュメントに対応させてみた
今年の5月にJava SE 7のAPIドキュメントをはじめとした、Java SE 7のドキュメントの日本語版が公開されました(Java SE7API日本語版提供開始、Java SE ドキュメント)。
バージョン6までのように「Java 7 HashMap」のように検索して(Googleなら「日本語のページを検索」に制限すると最初に出てくるようになります)Webブラウザで見るのでももちろんいいのですが、MacユーザとしてはやはりDashで見たいわけです。 ちなみにDashというのはMac/iOSなどのAPIドキュメントをキーワードからインクリメンタルサーチで高速に見ることができるツールで、私は重宝しています。ダウンロードすることでScala, Ruby, Python, Node.jsなどにも対応することができます。ちなみに無料でも使えますが、フルバージョンを購入してないと検索時にたまに数秒待たされるとのことだったので、速攻でポチりました。
DashでJava 7 SE API日本語版を対応できるようにするのにはちょっと面倒くさかったのでやり方をメモっておきます。なおJava APIドキュメントのライセンスで、インターネットでの再配布は許可されていないため、Docsetの再配布をする予定はありません。予めご了承ください。
ドキュメントの取得
いくつかキーワードを変えて検索してみたのですが、どうやらJava SE 7の日本語ドキュメントはzip書庫などでまとめて取得することができないようで、仕方なくスクレイピングで取ってくることにしました。wgetで再帰ダウンロードでもいいのかもしれませんが、リンクされてないページがあると嫌だったので英語版ドキュメントをunzipしたもののファイル構造から日本語ドキュメントをダウンロードするという方法を取りました。
Javadocをdocsetに変換するツールの修正
JavadocをDash用のDocsetに変換するツールがGitHubで公開されていたので取ってきます。
https://github.com/Kapeli/javadocset
ですがこれをそのまま使うと変換中に大量の警告が出力され、Dashに取り込んでもクラスやインターフェイスがほとんど読み込めません。 これはこのツールが英語版ドキュメントの書式にのみ対応しているため、クラス名などを取得するためのキーワードが違う日本語ドキュメントは正しく処理ができないんですね。
ということで、日本語ドキュメントに対応できるようにしたForkをGitHubに用意しました。
https://github.com/mtgto/javadocset/tree/japanese
英語版にはない、表現の微妙な差にハマりました(「〜 内のクラス」と「〜 のクラス」とか)。 使用上の注意として、masterブランチは上記の修正を入れてないので、もし使おうとする人はjapaneseブランチからビルドして使ってください。
Docsetに変換
あとはDocsetに変換してDashに取り込むだけです。 javadocsetをXcodeでビルドして、
javadocset Java /path/to/api
と実行するとJava.docset
が生成されます(/path/to/api
は日本語ドキュメント内のapiフォルダへのパスを入れてください)。
これをDashにインストールすればJava 7のドキュメントが検索できるようになっているはずです。英語版Javaドキュメントがすでにインストールされていて、もう不要でしたら削除しておきましょう。
終わりに
以上でJava SE 7日本語ドキュメントをDashで引くための方法についての説明は終わりです。
参考リンクにも入れましたが、Rubyの日本語リファレンスマニュアルをDash用に対応してくれている人がいるので、よろしければそちらもチェックしてみてください。
参考
Chromeで「サードパーティのCookieとサイトデータをブロックする」をオンにしているとはてなブログにログイン出来ない
例外的にblog.hatena.ne.jpをサードパーティ許可したらログインできるようになったが、釈然としない。
scala irc botでのbotの作り方
はじめに
この記事は、私がGitHubで公開しているscala-irc-botというプログラムの使い方とボットの書き方のチュートリアルです。 ScalaでIRCボットを書きたいという需要が非常に少ない目的のために書きました。
目次
scala irc botの紹介
scala irc botってなんですか
https://github.com/scala-irc-bot
私がScalaでirc botを書けるように作成しているプログラムです。 実際にIRCに接続するのにはPircBotというJava製のIRCクライアントを使用しています。
現在の最新バージョンは0.2.0-SNAPSHOTです。バージョンは大きく設計が変わるときに更新されます。プラグインに影響のない修正ではバージョンを上げません(mavenリポジトリの更新が面倒だからです)。
現在の使い方は sbt run
によって起動させるのを推奨しています。
性質的に常時起動しておくプログラムなのでデーモンのように使うほうがいいのかなあ。。。
irc botってなんですか
IRCでの誰かの発言などのイベントなどに反応して発言したり作業したり愛したり恋したりしてくれるプログラムです。 ときには喧嘩して殴りあったりするけれど、でもそんなお前のこと、そんなに嫌いじゃないぜ?っていう人格を持っています。
ircってなんですか
つ RFC1459
デプロイ方法
次のものを用意してください。
- sbt
- git
git clone
本体のコードはgithubで管理しているので、cloneで持ってきます。
git clone https://github.com/scala-irc-bot/scala-irc-bot.git
設定ファイルの記述
cloneしたディレクトリに移動し、configディレクトリの中に、Config.scalaというファイルを作成します。
Config.scala
import net.mtgto.irc.Config import net.mtgto.irc.config.BotConfig new Config { val hostname = "irc.example.com" // IRCサーバの名前 val port = 6667 // IRCサーバのポート val password = None // 必要ならSome("password")のように記述する val encoding = "utf-8" // 使用するエンコーディング val messageDelay = 2000 // メッセージ間の遅延(ミリ秒) val timerDelay = 60000 // タイマーイベント間隔(ミリ秒) val nickname = "scala-irc-bot" // ボットのニックネーム val username = "scala-irc-bot" // ボットのログイン名 val realname = "mtgto@example.com" // ボットのリアルネーム // channels val channels = Array("#mtgto", "#test") // JOINさせたいチャンネル // bots val bots = Array[(String, Option[BotConfig])]( // ここにプラグインの設定を記述する ) }
起動する
コンソールからsbt
で起動します。
sbt run
(初回のみ)コンパイルが実行され、設定ファイルやネットワークなどに問題が起きなければ、しばらく経つとIRCサーバにscala irc botが接続してきます。
ですが今のままではボットプラグインを何も入れてないので、何もしてくれません。
コンソール画面にexit
と入力して終了させましょう。
プラグインの作成方法 (シンプル)
ここからはまずはシンプルなプラグインを作成していきます。 ここでいうシンプルなプラグインというのは、
- 設定ファイルでボットプラグインごとのオプションを設定できない
っていう前提のものです。下の方にオプションを使う方法も載せてあります。
Scala + sbtで作る
今回作る環境は、
- sbt (バージョンはユーザの環境に依る)
- Scala 2.10.0
- PircBot 1.8.0
です。
最小構成では build.sbt
Echobot.scala
の2ファイルで構成されます。
echobot/build.sbt
// -*- scala -*- name := "EchoBot" organization := "net.mtgto" version := "0.1.0-SNAPSHOT" scalaVersion := "2.10.0" resolvers += "mtgto repos" at "http://scala-irc-bot.github.com/scala-irc-bot/maven/" libraryDependencies := Seq( "net.mtgto" %% "scala-irc-bot" % "0.2.0-SNAPSHOT" % "provided" ) scalacOptions ++= Seq("-deprecation", "-unchecked", "-encoding", "UTF8")
echobot/Echobot.scala
package net.mtgto import net.mtgto.irc.{Bot, Client} import net.mtgto.irc.event._ /** * 受け取ったメッセージをNOTICEで送り返すボット */ class Echobot extends Bot { /** * 誰かがPRIVMSGを書いた時に通知される */ override def onMessage(client: Client, message: Message) = { // メッセージが送信されたチャンネルに同じメッセージをNOTICEで送り返す client.sendNotice(message.channel, message.text) } }
ファイルを置いたら、
sbt package
と実行すると、 target/scala-2.10.0/echobot_2.10.0-0.1.0-SNAPSHOT.jar
が作成されます。
このjarファイルがコンパイルされたプラグインです。
プラグインをインストール
まず、作成した echobot_2.10.0-0.1.0-SNAPSHOT.jar
を scala-irc-bot/bots
フォルダの中に置いてください。
次に config/Config.scala
にボットプラグインの設定を記述します。
val bots = Array[(String, Option[BotConfig])]( // ここにプラグインの設定を記述する ("net.mtgto.Echobot", None) )
sbt run
すると画像のようにこちらの発言をNOTICEで繰り返してくれるようになります。
botテンプレートを使う (g8)
giter8用のテンプレートを作ってあるので、これを使うこともできます。
g8 scala-irc-bot/bot
version [0.1.0-SNAPSHOT]: organization [com.example]: net.mtgto name [IRC Bot Project]: EchoBot
こちらは先ほどの手順で作成した時に加えて、テスト用にSpecs2、ビルド用にsbt-assemblyの設定をしてあります。 慣れてきた場合や他ライブラリに依存するプラグインを作るときにはこちらをおすすめします。
プラグインの作成方法 (設定可能)
設定ファイルでボットプラグインごとのオプションを設定することができます。
設定ファイルに書いたオプションを読み込むには、net.mtgto.irc.config.BotConfig
を実装したクラスを作り、そのオブジェクトをプラグインのメインクラスのコンストラクタにもたせてあげればよいです。
実例を示してみます。今回は設定ファイルに書いたキーワードが書かれた時だけ反応するようにしてみましょう。 KeywordEchobotを作成します。
KeywordEchobot.scala
package net.mtgto import net.mtgto.irc.{Bot, Client} import net.mtgto.irc.event._ import net.mtgto.irc.config.BotConfig /** * BotConfigを実装したクラスを定義する必要がある。 */ case class KeywordEchobotConfig( val keywords: Seq[String] ) extends BotConfig /** * 特定のメッセージをNOTICEで送り返すボット * * コンストラクタでEchobotConfigを受け取る */ class KeywordEchobot(val config: KeywordEchobotConfig) extends Bot { /** * 誰かがPRIVMSGを書いた時に通知される */ override def onMessage(client: Client, message: Message) = { if (config.keywords.contains(message.text)) { // メッセージが送信されたチャンネルに同じメッセージをNOTICEで送り返す client.sendNotice(message.channel, message.text) } } }
これを先ほどと同じように sbt package
でビルドして、target/scala-2.9.2/keywordechobot_2.10.0-0.1.0-SNAPSHOT.jar
を scala-irc-bot/bots
にコピーします。
あとは config/Config.scala
に設定を書いてあげます。
val bots = Array[(String, Option[BotConfig])]( ("net.mtgto.Echobot", Some(net.mtgto.KeywordEchobotConfig(Seq("こんばんは", "おはようございます")))) )
Seqに好きな言葉を列挙してあげます。
あとは sbt run
すると、設定ファイルにある言葉が書かれた時にだけ応答してくれるようになります。
まとめ
簡単でしたが、scala irc botの導入方法とプラグインの作成方法を書きました。 多分ここまで読んでいる方はいらっしゃらないと思うのですが、さらにプラグインを作ってみたいという奇特な方がいらっしゃるようでしたらこの上なく幸せです。 まだサンプルプログラムが少ないのですが、私も幾つかプラグインを作っているのでよろしければそれを見てみてください。