温泉付きコワーキングスペースに行ってみた

GWアドベントカレンダー「使いたかったもの使ってみたカレンダー(1人アドベントカレンダー)」の8日目、5/4記事です。

気になってた温泉コワーキングスペースに行ってきました。

場所は秋葉原と御茶ノ水の間にあります。

RAKU SPA 公式サイト

温泉があり、コワーキングスペースがあり、wifiあり、ランニングステーションにもなり、翌朝8時までやってるのでお泊まりもできるという施設です。

良さそうなところ/面白かったところ

  • 温泉入って、作業して、また温泉入ってというサイクルができる
  • ランニングステーションにもなるので、皇居ランもできる
  • サウナがちゃんとある
  • 作業に疲れたら休憩がてら漫画を読める(そして作業には戻らなくなる
  • ごはん処もあるので一日入り浸れる

あんまりイケてないところ

  • 途中外出はNGなので、皇居ランからの温泉、休憩破産で皇居ランはできない
  • wifiがちょっと弱め・・・(場所によるかも)
  • 朝が11時からしか空いていない
  • GW中だからか、結構混んでた

総合評価

普段の土日の混み食い次第ですが、皇居ランからの温泉からの作業、そして温泉&サウナ入って帰るという
1日満喫コースが鉄板になりそうなぐらい、良い施設でした。
wifiは気になるので、テザリングかwimaxの用意が必要そうです。

関連記事

技術書典6 当日振り返り

技術書典6に出展してきたので振り返りです。
前回記事に続き、これから初めて出展する!という方の参考になればいいなと思います。

前回記事 → 技術書典6に出すまで振り返り

被チェック数の推移と売れ行き

おそらくみんなが気になるのはこれですね。
被チェック数を直前まで記録していなかったため、直近のみとなりますが、こちらです。
スクリーンショット 2019-04-14 21.26.05.png

実施4日前に100を超え、当日朝で240、当日終了時で300超えました。
それに対して販売数は106冊(物理本98冊+PDF版8冊)でした。

目安として考えるのであれば、4日前の被チェック数分、もしくは当日朝のチェック数の40%ぐらいでしょうか。

14:30に物理本が売り切れてしまったので、もしかしたらもう少し印刷を多めにしても良かったかもしれません。

ブースデザイン

IMG_2943.PNG

サイズ

思ったより狭いです。立ち読みする人が隣のブースにはみ出て迷惑になることがあるので、適宜そっちに行かないように促す必要がありました。

金額表示

見本誌に値段を書いていたけれども、誰かが立ち読みしていると値段がわからない事案が発生しました。当たり前ですね。

見本誌に書く値段とは別に、明示的なプライスカードを用意するべきでした。

光り物

NexPixcelの光る眼鏡をずっとつけていましたが、時々きになって立ち寄ってくれる人がいたのは良かったです。やはり、光る/動く/音がなるは人の目を引いて良いです。
ここはハードウェア関係本の人は特色を一気に出していきたいですね。

ポスターとか

机が人混みで隠れるので、縦方向に伸びる何かがあったほうが良かったです。
ポスター+三脚とか。

本を手に持って掲げながらの呼び込みはある程度効果があったのかなと思います。

見本誌の数

1冊でやろうとしたが、無理でした。見本誌待ちの列ができてしまいます。
2冊はほしいです。
(今回は見本誌じゃなくても立ち読みいいよ!って雰囲気でごまかしました。)

100冊売るなら見本誌2冊、200冊売るならその倍とかいるんですかね。

簡単後払いの対応

とても便利でした!これの対応は必須と言えると思います。
来客者も慣れた感じでしたし、小銭の対応がなくなるのはでかいです。

簡単後払いなら小銭の心配しなくていいのでギリギリまで値段下げる・・とかしたいですね。(現金:1000円、後払い900円とか)

人関係

売り子

2人は必須です。1人だとトイレにもいけない・・・。

掛け声

したほうがお客さんの入りが良かったです。
特に、皆さん丁寧なのか、「手にとっていいですよ」の一言がないと見本誌を手に取らない方々が多かったです。
見本誌なので勝手に取って読んでいいんですけどね。

ブース巡り

開始前は優遇になるので(?)販売禁止らしいですが、11時の会場してからお客さんが入ってくるまでの間の数分に駆け込み買いをする方が多かったです。

今回は2人で、最初は慣れるために2人体制、30分たった頃に1人ずつ交代でブースめぐりしました。行きたいブースの事前チェックをしておいたので、スムーズに巡って返ってこれて、自分のブースにいない時間も少なくできてよかったです。

持ち物関係

あってよかったもの/ほしかったもの

  • はさみ
  • セロハンテープ
  • ふせん/ラベルシール/スケッチブック
  • 太字のペン
  • プライスカード
  • ポスタースタンド
  • 飲食物

ブース準備時

印刷所から届いていた箱を開けるのにハサミが必要です。また、ブース設計になにかとセロハンテープが活躍しました。

今回、ふせん+セロハンテープで「見本誌」や「1000円」と書いていましたが、ラベルシールがあればそちらのほうがきれいだったかもしれません。
ふせんにしろラベルシールにしろ、それに書くための太字のペンは持っていくべきでした。

ポスタースタンドやプライスカードは前述のため省略.

飲食

お昼準備しましたが、食べる暇なくそのまま持ち帰ることになりました。食べるの忘れるぐらい熱中してたとも言えます。

逆に水分は、500mlペットボトル3本用意していきましたが足りず、4本目を買いに行きました。自販機は会場出てすぐのところにあるので、再入場規制期間(AM?)以外は手軽に買いに行けると思います。

お客さんの反応

見本誌の見方としては下記のパターンが多かったです。

  • ぱらぱらと全体を見る
  • はじめにをじっくり見る
  • 目次をみる

つまり、

  • ぱらぱらと全体を見る → 写真/イラストに惹かれる
  • はじめにをじっくり見る → 導入文章に惹かれる
  • 目次をみる → 全体構成に惹かれる

それ以外の、例えば第3章の本文なんて、誰も見本誌では読んで無いんじゃないでしょうか。
本の文章の中でも、イラストや写真でわかりやすくなっているか、導入文書できちんと人が惹きつけられるか、目次を見ただけで内容イメージができて興味が沸くか というは、本を作る中でも特に重要そうです。

まとめ

いろいろもっとこうしたら良かったーはあるものの、十分合格点を出せるぐらいの展示はできたと思います。えいやっ!っていってもなんとかなるものなので、とりあえず申し込んで見る からのてがるな参加が増えればいいなと思っています。

技術書典6に出すまで振り返り

技術書典6に当選したので初めて出展します。技術同人誌を出すにあたって初めてで試行錯誤したところがあったので、次回に向けての記録です。
初出展する人の参考になったら嬉しいです。

なんで出展したのかは別記事で書きました。
https://note.mu/9wick/n/nb9afa80518c1

また、当日振り返りは更に別記事です
技術書展6当日振り返り
https://qiita.com/wicket/items/f1ab47ca4d7e447846be

出展する本

Web技術でIoTをしよう」 @9wick 著 / 36ページ / 本 もしくは PDF

unnamed.png

Web技術をそのままつかって、バーチャルな世界(HTML)とリアルな世界(センサ・モーター)をつなぐIoTを始めましょう!
Web知識でIoTができるクラウドボードobnizの使い方と、それをつかった作品のレシピを紹介します。

・HTMLで書くIoTプログラム
・Webの知識だけでハードウェアを動かすobnizとはなにか
・「Hello world」から始めるIoTプログラムの書き方
・LEDなどの部品の使い方
・具体的なシステムを作る上でのサンプルコード/解説

制作

期限設定

文章を書く、というのは思ったよりも体力と時間がかかるので、締切をはっきりと意識して取り組みました。

自分は1週間前に印刷所に提出を期限にしました。
1週間前だったら通常料金で取り扱ってもられる印刷所が多いようです。

それより早いと割引(10〜40%OFFとか)があり、それより遅いとだんだん特急料金がかかるようです。ただ、お金さえ積めば印刷はしてもらえそうでした。

印刷所に頼まず自作する場合はまた別の期限設定になりそうですね。

本文の作成

書き方

とりあえず最初から書く、というよりは目次を作る形で、全体構成を作りました。
4ページの寄稿と、自分でまるまる一冊つくるのを同時並行させましたが、どちらもどういう話の構成にするのか考えるのに目次を作りました。

話の構成から考えることで、最初の数ページでこだわりすぎて先に進まない・・ということがなくなった気がします。

使用ツール

最終的にPDFにできればなんでも良さそうです。
wordで書いてる人もいるようです。

今回はRe:viewというソフトを使って書きました。拡張Texみたいなもので、テキストベースで書きます。PDFだけでなく、epubやmarkdown、HTMLに出力できるのがメリットのようですが、結局PDFにしか出力しませんでした。

良かった点

  • 書きやすい
  • textベースなのでgit管理がしやすい
  • docker環境を提供している人がいて、環境セットアップで躓かなかった
  • 章単位でファイルを分けられて、管理がしやすい

悪かった点

  • Texベースなので、ちょっと論文っぽさが増してしまう
  • 商業誌や雑誌のようなちょっとゆるふわな本をつくるには向いてなさそう

みなさん何で書いているんですかね・・・。

レビュー

レビューしてくれる人がいなかったので、自己レビューでやりました。
チェックするときはやはり紙に印刷して読むのが一番はかどりました。

プリンターは家にはなかったので、セブンプリントで印刷してチェックしました。

他人に見てもらえるのであればそちらのほうが良さそうです。

表紙の作成

印刷所を使う場合、.aiや.epsファイルを作成する必要があります。
本文とは別ファイルで良いので、本文を作ってる間は気にせず、印刷所に頼む直前に作りました。

Adobe関連のソフトは持っていなかったですが、
普段愛用しているaffinity designerがepsファイルを出力できたのでそちらで作りました。

また、表紙/裏表紙と分けて考えるのではなく、1枚の紙で本をくるむ のように考えて、
表裏連続したイラストを作ることも多いようです。 自分は表裏別々に考えていたので驚きました。

印刷所ごとに表紙フォーマットが別々であるようで、作り始める前に印刷所を決めたほうが良さそうでした。そのフォーマットも、厚さ2mm用、4mm用、6mm用と別れていて、ページ数や紙の材質によって変わるようです。印刷所のホームページでシミュレーターを使うと2.6mmの厚さだったので、2mmのを使いましたが、いまのところ問題なさそうです。

印刷

印刷の方法について

外部に印刷を依頼するか、自分で印刷するかという選択肢がまずあり、
外部に印刷を依頼するときはどの印刷所に依頼をするか というカテゴリになるようです。

自分で印刷のメリット

  • ギリギリまで執筆できる
  • プリンターがあれば自宅で完結できる

自分で印刷のデメリット

  • 本としてのクオリティがちょっと残念(紙の質とか)
  • 印刷冊数によっては印刷に時間がかかる
  • 印刷後の製本作業が大変
  • 当日持っていくのが大変(紙は重い)

外部に印刷のメリット

  • きれいに印刷できる
  • 製本がしっかりしている
  • 数量が多くても大丈夫

外部に印刷のデメリット

  • 印刷所ごとに納期がある(早割もあるので結構気にする)
  • 当日ブースに届けてくれるので運ばなくて良い
  • 当日まで実物を見れないので不安
  • 印刷所選びやオプションに悩まされる

ちなみに、これのいいとこ取り(?)な選択肢としてキンコーズがあり、
試作で使ってみたけどよかったです。

印刷所について

ねこのしっぽさんと日光企画さんがバックアップ印刷所としてサポートしてくれます。
どちらのHPもみてみましたが、今回はねこのしっぽさんで印刷しました。

本当は料金比較して、どっちがやすいか/どっちのクオリティが良いかとかしたかったのですが、
そもそも日光企画さんのHPは私には難しすぎて、どういうものを何部だしたらいくらになるのか、がぱっとわからなくて、比較に挫折しました。

ねこのしっぽさんはHP上の導線がわかりやすく、すぐいくらになるかわかりました。

印刷の方式について

オンデマンドとかオフセットとか、中綴じとかいろいろあってそもそもよくわかりませんでした。
色んな所でおすすめはこれ!とか書いてありますが、なんでおすすめするのか?違いはなにかがわからずモヤモヤしてました。

そんな中調べた結果はこちら

オンデマンド/オフセット

  • 印刷方式の違い
  • オフセットがきれい/オンデマンドがそれなり
  • 細かい部分に差が出やすい(細い線とか)。 つまり、表紙よりも本文に差が出やすい
  • 表紙だけきれいならいいや というプランはなく(一般的ではない?)すべてオンデマンド/すべてオフセット/表紙オフセット+本文オンデマンドの3択のよう
  • オフセットがきれいだから高いと思いきや、部数によってはそちらのほうが安い(200部以上?)。つまり、部数が多いならオフセット1択。

中綴じ/無線

  • 製本の仕方
  • 中綴じは1枚の紙に両面で4P分印刷して、半分におってホッチキスでとめる方法。小学校とかの遠足のしおりとかでやりそう。
  • 無線は普通の本のようにする方法。
  • 中綴じは40Pぐらいまでしかホッチキス的に難しいらしい。でも家でも作れる。
  • 外に頼む前提であるならば、中綴じより無線のほうが上位互換っぽい。唯一のデメリットは見開きイラストとかあると真ん中の部分が見えない とのことだが、そもそも技術所で見開きイラストは使わないと思う。

紙の種類

・・・正直良くわからなかったので、選択肢の上がきっとおすすめだろうと選びました。
印刷所にいって見本を見せてもらうべきだったかもしれません。
選んだのはこちらです。

  • 本文:上質紙 90kg
  • 表紙:ホワイトポスト 180kg (PP無し)

入稿について

印刷所のHPに言われるがまま入稿しました。
フローとしては全く躓くことなく完了しましたが、入稿完了後に電話がかかってきて、
誤字があること/表紙の入稿フォーマットが違うことの連絡をいただきました。

誤字のチェックは業務範囲外なのにおしらせいただけてとても助かりました。表紙の入稿フォーマットはなんどか試してみたのですが、ベースの知識が無いからか、こちらの修正が先方の要求とちょっと違ったようで、最終的には先方でやっていただきました。
ありがとうございます。

発行部数について

こちらもよくわからないのですが、とりあえず100部にしました。
このぐらいなら全く売れなくても我慢できるなという出費で決めました。

そもそもどれぐらい売れるのかわからないのですが、さらに被チェック数に惑わされて混乱します。
あんまり伸びないなーとみていたら、技術書典1週間前の印刷数量をきめるタイミングになって、ちょっと伸びが増加したりして、どこまで参考にしてよいかわからなかったです。

技術書典が終わったら、被チェック数と販売数の関係でも見てみたいと思います。

オンライン配布方法

選択肢としては

  • PDFにパスワードを掛けて配賦
  • ダウンロードに共通パスワードが必要なサービスで配賦
  • シリアル番号管理できるサービスを使って配賦

※あとで気づいたが、技術書典公式の簡単後払いにダウンロード機能(β)がついたらしい。次回これ試してもいいかも。

twitterで聞いてみたら「シリアル番号管理できるサービスを使って配賦」が一般的のようでした。PDFパスワードは利用者が不便です(開くたびにパスワードが必要)。

シリアル管理ツール

シリアル番号管理できるサービスを使って配賦のサービスとして
対面電書があります。
シリアル番号管理でき、そのカードの印刷までサポートしてくれるようです。

カード印刷

印刷所に印刷を頼むか、自分で印刷するかになりますが、
原稿と違って1枚1枚シリアルが異なるカードを印刷する必要があります。

今回は時間がなかったこともあり、印刷所に頼めず、キンコーズで印刷しました。
印刷所に頼むときはバリアブル印刷がキーワードなので、次回は使ってみたいです。

NimbusKitのデバッグ機能も使ってみた!

昨日に引き続きNimbusKitをいじってます。 今日はNimbusKitでのデバッグです。 NimbusKitのデバッグは

  • 導入が簡単
  • PCいらずでアプリでバッグが出来る

というのが特徴みたいです。

NimbusKitのデバッグは組み込みが簡単

たったの2行でとっても簡単に組み込めるようです。

1
2
3
4
5
6
7
8
9
10
- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
[NIOverview applicationDidFinishLaunching];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
CatalogTableViewController* catalogVC = [[CatalogTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
_rootViewController = [[UINavigationController alloc] initWithRootViewController:catalogVC];
self.window.rootViewController = _rootViewController;
[self.window makeKeyAndVisible];
[NIOverview addOverviewToWindow:self.window];
return YES;
}

この中で、デバッグ用に追加されたコードは

1
[NIOverview applicationDidFinishLaunching]; [NIOverview addOverviewToWindow:self.window];

の2つだけ。 どうやら、[NIOverview applicationDidFinishLaunching];のほうでデバッグ画面を表示する領域を確保して、[NIOverview addOverviewToWindow:self.window];で実際に画面を追加しているみたいです。 実際に実行すると、画面の上にデバッグ画面がついかされます。 ここで一つ注意点があって、このデバッグ画面によって当然ほかで使える画面サイズが変わります。 iPhone5で縦長になった時の対応をきちんとしていれば多分大丈夫だとは思うのですが、画面サイズがどんな状態でも動くようにしていないと、ここで変になるかもしれません。(TabBarが画面外に表示されてしまう とか)

デバッグ画面でできること

では追加されたデバッグ画面で何ができるのかというと、

  • メモリの使用量(グラフ)
  • ハードディスクの使用量(グラフ)
  • メモリーキャッシュの使用量(グラフ)
  • コンソールログ(NSLogの出力)
  • コンソールログの設定

の5つの画面があります。横にスライドさせると画面が切り替わります。 ・・・どれもmacをつないでデバッグしてる時は普通に見れる者たちばかりですよね。
NimbusKitがすごいのは、それらがアプリ単体で見れる!というところです。 特に個人開発者になるのかなとは思いますが、アプリをリリースする前は実際に日常で使ってバグがないか、使いやすいかなど検証すると思います。 日常で使ってバグがないか確認している時に、ふと画面の上を見ればログが見えたり、メモリの使用量が見えたりするんです! 一日中Pcの前に座って開発できる人には不要のものかもしれませんが、日曜プログラマー的な人には重宝する機能な気がします。
というわけで、日曜プログラマーにおすすめのNimbusKitのデバッグ機能でした!

NimbusKitでiPhone画面デザインがCSSでできるというのを試してみた

GoogleMapがiPhoneでリリースされて、それにはNimbusKitが使われてるらしい! NimbusKitではCSSでViewの外見が設定できるらしい! って噂を聞いたので、噂のNimbusのサンプルをいじってみました

NimbusKitでできること

サンプルには三種類のプロジェクトが入ってて、その中はサンプルがいっぱい入ってて・・・という普通の構成でした。 機能としては大きく分けると2つ、「みんなが使ってたもののコードが簡単にかけるようになったよ」というものと「Nimbusだからこそこれができるよ!」というものに勝手に分けました。 まず、「みんなが使ってたもののコードが簡単にかけるようになったよ」は、見ててもあんまし面白く無いので省略。 ちょっとだけ書くと、UILabelの拡張やらNavigationBarの色変更、ネットワーク経由の画像表示などです。 それぞれ個人で工夫してクラス化とかしてたと思いますが、それをまとめた感じです。 メインはもう片方の「Nimbusだからこそこれができるよ!」の方。 こちらは

  • CSSがViewに適用できる
  • デバッグコンソールが付けれる

の2つ。 これについてちょっと書いて行きたいと思います。 今日のところはCSSの方だけです。 明日デバッグの方書きます

CSSがViewに適用できる

まず使い方から。 サンプルによると、まずcssをロードします。 このときキャッシュが効くようにしてますね。すべてのViewControllerで共通のcssを使うことを想定しているのかもしれません。 そしてNIDOMというのを作成しておきます。スタイルシートの管理者的な扱いでしょうか。

1
NIStylesheetCache* stylesheetCache = [(AppDelegate *)[UIApplication sharedApplication].delegate stylesheetCache]; NIStylesheet* stylesheet = [stylesheetCache stylesheetWithPath:@"root/root.css"]; _dom = [[NIDOM alloc] initWithStylesheet:stylesheet];

そして、普通にViewをつくっていくのですが、

1
_backgroundView = [[UIView alloc] init]; CGSize boundsSize = self.view.bounds.size; _backgroundView.frame = CGRectMake(floorf((boundsSize.width - squareSize) / 2), floorf((boundsSize.height - squareSize) / 2), squareSize, squareSize); _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhiteLarge]; [_activityIndicator sizeToFit]; [_activityIndicator startAnimating]; _activityIndicator.frame = CGRectMake(floorf((_backgroundView.bounds.size.width - _activityIndicator.bounds.size.width) / 2.f), 10, _activityIndicator.bounds.size.width, _activityIndicator.bounds.size.height);

途中で、NIDOMにViewを登録してあげます。

1
[_dom registerView:_activityIndicator]; [_dom registerView:_backgroundView withCSSClass:@"noticeBox"];

classはView側に書くところがないので、DOMに登録するときに一緒に指定してあげるみたいです。 これ以外は普通です。ちゃんとaddSubviewもしてあげます。 CSS側は

1
.noticeBox { background-color: rgba(32, 32, 32, 0.5); border-radius: 10px; border: none; } UIActivityIndicatorView { -ios-activity-indicator-style: white-large; -ios-autoresizing: left right bottom; }

とこんなかんじです。 noticeBoxクラスに指定できるのはもちろん、普通のクラスの方のUIActivityIndicatorViewを対象にすることもできるようです。 適用可能なルールは

1
static NSString* const kTextColorKey = @"color"; static NSString* const kHighlightedTextColorKey = @"-ios-highlighted-color"; static NSString* const kTextAlignmentKey = @"text-align"; static NSString* const kFontKey = @"font"; static NSString* const kFontSizeKey = @"font-size"; static NSString* const kFontStyleKey = @"font-style"; static NSString* const kFontWeightKey = @"font-weight"; static NSString* const kFontFamilyKey = @"font-family"; static NSString* const kTextShadowKey = @"text-shadow"; static NSString* const kLineBreakModeKey = @"-ios-line-break-mode"; static NSString* const kNumberOfLinesKey = @"-ios-number-of-lines"; static NSString* const kMinimumFontSizeKey = @"-ios-minimum-font-size"; static NSString* const kAdjustsFontSizeKey = @"-ios-adjusts-font-size"; static NSString* const kBaselineAdjustmentKey = @"-ios-baseline-adjustment"; static NSString* const kOpacityKey = @"opacity"; static NSString* const kBackgroundColorKey = @"background-color"; static NSString* const kBorderRadiusKey = @"border-radius"; static NSString* const kBorderKey = @"border"; static NSString* const kBorderColorKey = @"border-color"; static NSString* const kBorderWidthKey = @"border-width"; static NSString* const kTintColorKey = @"-ios-tint-color"; static NSString* const kActivityIndicatorStyleKey = @"-ios-activity-indicator-style"; static NSString* const kAutoresizingKey = @"-ios-autoresizing"; static NSString* const kTableViewCellSeparatorStyleKey = @"-ios-table-view-cell-separator-style"; static NSString* const kScrollViewIndicatorStyleKey = @"-ios-scroll-view-indicator-style";

の全部で25個みたいです。 ちょっと少ない気もしますが、今後に期待します。 これらのコードから、次の画面ができちゃうわけです。 (このページのコードだけだと省略部分が多すぎてわかりづらいかもしれません・・・) サンプルいじってて思ったのは、HTMLのCSSが使える!という形ではなく、iOSのデザイン部分をコードから分離できるという本来のCSSの意味合いでコードが作られた感じがしました。 HTMLが必要最低限書いてデザイン的な面はCSSで外部ファイルにしてサイト統一なんだから共通化しようよ!という流れできたように、 iOSのViewControllerだって最低限だけ書いて、デザイン的な面は外部ファイルにしていろんなViewControllerで共通に使おうよ!といった感じでしょうか。 Twitterとか見てると、HTMLで使えるものが使える!と勘違いしている人が多そう(自分も含め)ですが、ちょっとそれとは違うかなぁと思いました。 ただ、デザインの外部ファイル化に関してはすごいいいな!って思います。 もしかしたらCSSができることによって、デザイナーさんと分業できる!とかなるとさらにいいなと思いました。

NSURLConnectionでの文字エンコード

日本語だからこそつきまとう文字エンコード問題にまたつまづきました。 NSURLConnectionでダウンロードしたファイルの文字エンコードがわからず、文字化け・・・・。 htmlの中荷は買いてあるんだけど、それを見るためには一度NSDataからNSStringにしたいけどそこでエンコードがわからないという鶏と卵問題になりかけたので、ちょっとメモっときます。

ヘッダ情報からエンコードを取得する

まず一番楽なのが、このヘッダ情報からエンコードを取得する方法です。 NSURLConnectionのデリゲートでヘッダが帰ってきた時に一緒にエンコード名が取得できます。

1
2
3
4
5
6
7
 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ NSString \*textEncodingName = [response textEncodingName]; } 

```objective-c
あとはこれをもとに、エンコードを取得してあげます。

```objective-c
NSString \*encodingName = [textEncodingName lowercaseString]; encodingName = [[encodingName componentsSeparatedByString:@"-"] componentsJoinedByString:@""]; encodingName = [[encodingName componentsSeparatedByString:@"_"] componentsJoinedByString:@""]; NSStringEncoding encoding; if ([encodingName isEqualToString:@"eucjp"]) { encoding = NSJapaneseEUCStringEncoding; } else if ([encodingName isEqualToString:@"shiftjis"] || [encodingName isEqualToString:@"sjis"]) { encoding = NSShiftJISStringEncoding; } else { encoding = NSUTF8StringEncoding; } NSString encodedString = [[[NSString alloc] initWithData:self.downloadedData encoding:encoding] autorelease];

ただ、ちょっと気をつけないといけないことがあって、

  • そもそもヘッダにエンコード情報が入っていないことがある
  • エンコード名は結構自由に入れられるらしいので、きっちり対応するのは難しい

って問題があります。 でもこれが一番簡単&実行できるときは確実なので、まずこれを試したあと、他の試すのがいいかと思います。

総当りで変換する

とりあえず、NSStringのinitWithData: encoding:はエンコードが間違ってるとnilが帰ってくることを利用して

1
NSStringEncoding encodes[] = {NSJapaneseEUCStringEncoding, NSShiftJISStringEncoding, NSUTF8StringEncoding}; if(!encodedString){ for (int i = 0; i < 3; i++) { encodedString = [[[NSString alloc] initWithData:self.downloadedData encoding:encodes[i]] autorelease]; if(encodedString){ encoding = encodes[i]; break; } } }

と無理やりやってしまう方法もあります。 ちょっと動作が重そうなのと、特殊文字が入っているとアウトなこと以外は万能そうな方法です。

他にもhtml内部に書かれた文字コードを取得して〜とかあると思いますが、ちょっと難しい&めんどくさかったので普段そんなに使わないだろうということで割愛。 そもそも普通の人はエンコードがわからない状態のものをDLすることってないんですかね??

UIWebViewのリンク長押しを簡単にハックする

UIWebViewを長押しすると下からニュっとアクションシートが出てくるわけですが、これの中身を変えたくなりました。 ネット上で探したところ・・・・これとか解決策っぽいのはあったんですが、なんかもうやること多いし、UIWindowのサブクラスを作らなきゃいけないし、英語だし、なんか嫌だったので、もっと簡単な方法でハックしてみました。 ちょっと精度が悪かったり、反応しない時があったりとポンコツ気味ですが、簡易的に作るならこれぐらいがいいなーって感じです。

やり方

大雑把な手順としては

  1. 本来のリンク長押しの機能をオフにする
  2. jsでリンク長押しを検知してobj-cの方に教えてあげる
  3. 普通にアクションシートを出してあげる

という3段階構成です。 「本来のリンク長押しの機能をオフにする」と「jsでリンク長押しを検知してobj-cの方に教えてあげる」はどっちもjsなので、 具体的にはとあるjsを読み込んで、通知が来たらアクションシート出すだけというお手軽構成です。

本来のリンク長押しの機能をオフにする

css(style)で–webkitTouchCalloutをnone指定にしてあげるとでなくなります。 こういうのはSafari Web Content Guideに書いてあるっぽいです。 で、これをjsでかくと

1
document.documentElement.style.webkitTouchCallout = 'none';

です。つまり

1
[webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout = 'none';"];

とやれば長押ししてもきかなくなります

jsでリンク長押しを検知してobj-cの方に教えてあげる

ここが少しめんどくさくて、jsのタイマー使ってリンクの長押しを検知しーとかやらないといけないです。 といっても、中身がわからなくてもいいから使えればいいんだ!っていうなら簡単で、次のjsをロードすればいいだけです。

1
var NVTimer = { currentUrl : null, currentTitle : null, start : function(url, title){ NVTimer.currentUrl = url; NVTimer.currentTitle = title; setTimeout("NVTimer.finish('" + url + "')",750); }, cancel : function(url){ NVTimer.currentUrl = null; NVTimer.currentTitle = null; }, finish : function(url){ if(NVTimer.currentUrl === url){ document.location = "nv://taphold"; } } }; (function(){ var elements = document.getElementsByTagName("a"); var length = elements.length; var i = 0; for(i = 0; i< length; i++){ if(elements[i].href !== undefined ){ elements[i].onselectstart = function(){ return false; }; elements[i].ontouchstart=function(){ NVTimer.start(this.toString(), this.innerHTML); return true; }; elements[i].ontouchcancel=function(){ NVTimer.cancel(this.toString()); return true; }; elements[i].ontouchend=function(){ NVTimer.cancel(this.toString()); return true; }; elements[i].ontouchmove=function(){ NVTimer.cancel(this.toString()); return true; }; } } })();

これをロードすれば、リンクを長押しした時に「nv://taphold」といったURLに移動しようとするので、これをobj-c側で検知してあげます。 ロードするときは、最初の「本来のリンク長押しの機能をオフにする」の方のjsと一つにまとめて、xxx.jsって形でファイルに保存して ページのロード完了時に読み込むのがおすすめです。 ※jsファイルをそのままプロジェクトに追加しただけだとリソースファイル扱いになってないので注意

1
- (void)webViewDidFinishLoad:(UIWebView *)webView{ NSString \*nvtimer = [_webView stringByEvaluatingJavaScriptFromString:@"typeof NVTimer"] ; if([nvtimer isEqualToString:@"undefined"]){ NSString \*touchhold = [[NSString alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touchhold" ofType:@"js"] encoding:NSUTF8StringEncoding error:nil]; [webView stringByEvaluatingJavaScriptFromString:touchhold]; [touchhold release]; } }

普通にアクションシートを出してあげる

これはもう簡単で、こんな感じ。

1
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ if([request.URL.scheme isEqualToString:@"nv"] && [request.URL.host isEqualToString:@"taphold"] ){ [_actionSheetTmpUrl release]; [_actionSheetTmpTitle release]; _actionSheetTmpUrl = [[_webView stringByEvaluatingJavaScriptFromString:@"NVTimer.currentUrl"]retain]; _actionSheetTmpTitle = [[_webView stringByEvaluatingJavaScriptFromString:@"NVTimer.currentTitle"]retain]; NSString \*title = [NSString stringWithFormat:@"\\"%@\\"\\n%@",_actionSheetTmpTitle,_actionSheetTmpUrl]; UIActionSheet \*sheet = [[UIActionSheet alloc] initWithTitle:title delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"リンク先を開く",@"リンクをコピー",nil]; [sheet showInView:[UIApplication sharedApplication].keyWindow]; [sheet release]; return NO; } return YES; }

_actionSheetTmpTitle と _actionSheetTmpUrl にそれぞれリンクのテキストとURLを保存しているので、アクションシートからのdelegateがきたらこれの情報を元に処理してあげればOK!

というわけで、簡易的なリンク長押しハックでした。 精度的には(人によるけど)50%ぐらいで、モックアップ程度ならこれでいいかな〜という感じです。 売り物だとちょっと精度が低い。。。かもしれません。

iPhoneアプリでユーザーのタッチを禁止する

iPhoneアプリで、データをDLして読み込んで〜みたいな処理をする時、ユーザーの操作を禁止したい時があります。 もちろん、本来はユーザーの操作を禁止せずに、非同期で処理するのが一番いいのでしょうが、 モックアップを作る時だったり、実装に手間をかけてられないときなどもっと簡易的に実装したいことがあります。 どうやるのかな〜と調べてみたところ、案外簡単でした。

1
[[UIApplication sharedApplication] beginIgnoringInteractionEvents]; [[UIApplication sharedApplication] endIgnoringInteractionEvents];

この2つのメソッドで、ユーザーのタッチ操作を完全に無視できます。 処理を間違えると永遠にタッチができないアプリになりかねないので、使うときは要注意です。

FacebookアプリでFireFoxのスクロールバーが消えない問題

ちょっとFacebookアプリ(iframeで組み込みのやつ)を作ることになって、色々なブラウザでテストしていたのですが、その時にFireFoxだけなぜかスクロールバーが消えませんでした。 色々なブログでは

1
<script type=”text/javascript” src=”http://connect.facebook.net/en_US/all.js”></script> <div id=”fb-root”></div> <script type=”text/javascript”> FB.init({ appId : ‘アプリID’, status : true, cookie : true, xfbml : true, logging : true }); FB.Canvas.setAutoResize(); </script>

のようにしてスクロールバーを消すよ!みたいなことが書いてあるんですが、ダメだったのでちょっと試行錯誤してみました。 その結果、facebookアプリの設定の部分の縦の長さを固定にすることで対処できることがわかりました。 ただ、立て固定にしちゃっていいの?と疑問だったのですが、jsでの縦長さ変更は有効らしく、なんでこんな設定があるのだろう?というぐらい固定化の意味は無さそうです。 というわけで、firefoxでスクロールバーが出て困ったときはfacebook側の設定でたて高さを固定するといいと思います!

関連記事

iPhoneアプリ開発でそろそろ@2xなしの画像はいらないかもしれない

忙しい時期が終わってブログをかこう!とおもったら前の記事から1ヶ月もたってて少し驚いています。。。。 やっぱ忙しくても小さな記事書けるようになりたいですね。 さて、世の中はiPhone5がでて、アプリ開発者は頑張って対応をしている時だと思うんですが、このときちょっと知り合いに 「3GSってもう切っていいよね?」って言われて初めて3GSを切れる=画像の種類がひとつ消えるということに気づき、 Retinaになってからもうそんなに時間がったたのかと思いつつ、3GS用の画像が切れるのか、また、切ったらどうなるのかを検証してみました。

3GSのシェア

まず、そもそも切れるのかどうかという点から、3GSのシェアを調べてみた(調べてもらった)ところ、 とあるアプリでの3GSのシェアは1.8%でした。 個人的には5%を切っているので、十分に3GSを切る検討をする価値があるのではないかと思います。

減る容量

おもに3GS対応をやめるとことで変わるのは@2xなしの画像の有無だと思うので、どれくらい容量が減るのか考えてみました。 みなさんたぶん主に使う形式はpngだと思うので、検証したのはpngのみです。 @2xなし画像の割合 は @2xなしの画像の容量 / (@2xなしの画像の容量 + @2xの画像の容量) でだしています。 (つまり、@2xなし画像を消した時に容量が減る割合)

@2xなしの画像の容量

@2xの画像の容量

@2xなし画像の割合

画像1(320x480px)

10,095バイト

13,788バイト

42.2%

画像2(57x57px)

4,350バイト

10,297バイト

29.6%

画像3(32x32px)

815バイト

1,791バイト

31.2%

こうみると、30%~40%ぐらいの容量削減が見込めそうですね。 画像がメインのコンテンツの場合、30%も容量が減ればDL時間にも大きく影響してきそうです。

対応しない場合3GSではどうなるのか

自分は3GSを持っていないのでシミュレータで我慢して試してみました。 実機ではないという意味では微妙なのですが、シミュレータで試す限り@2x画像だけで何の問題もありませんでした どうやら勝手に@2xの画像が縮小されて使われているようです。 ただ、シミュレーターでのお話なので、実機でメモリが〜とかいう面は知りません。

結論

今後は@2xなしの画像ファイルはなくてもいいかもしれません。