TECH PLAY

株式会社LIFULL

株式会社LIFULL の技術ブログ

652

大坪と申します。Simple Exampleシリーズと称して「ググれば見つかるけど、ちょっとわかりづらい」iOS上でのテクニックについて ・実行できるサンプルプロジェクト付(動かないとわかんない) ・肝心な部分を動かすのに必要最低限のコードを書く。余計なものは一切つけない(ごてごて余計なものがあるとどこが肝かわからない) をモットーにサンプルコードを解説&公開していきます。第一弾は「UICollectionViewのframeをアニメーション付きで変更する」方法について。 UICollectionViewというのは私見では実に偉大な画面部品で、あちこちで使いたくなります。その際「何かのアクションでUICollectionViewのframeを変更する」ということがあると思います。 というわけで、 githubにおいた のサンプルコードを実行してみてください。こんな画面が表示されるはずです。 左端にUICollectionViewが表示されています。画面右側一番上の"Frame Change"を押してみてください。いきなりUICollectionViewの外枠とセルが変化します。 プログラム的には UICollectionView.frame = newFrame; (ViewController.mのsimpleChange:(UIButton*) buttonの処理 としただけです。 これで用が足りる場合もあるでしょうが、iOSでプログラムを書いていると「アニメーションで変化させたい」と思うことでしょう。実際UIView animationWithDuration:は偉大で、ブロックの中に変化させる処理を書けば、たいていのことはアニメーションで変化させてくれます。ではさっそくframeの変更処理をUIView animationWithDuration:の中にいれてやりましょう。 画面のFrame Change + UIView animationを押すとこの処理が実行されます。 確かにアニメーションするのですが、なんとなく動きが期待と違うと思います。とくにUICollectionViewの幅が狭くなる時には、セルが縦一列にいきなり移動し、そのあとアニメーション付きでUICollectionViewのframeが変化する。これはあまり美しくない。 というわけで、一番下のCombo Changeを押してみてください。frameの変形だけではなく、セルの移動にもアニメーションがついたのがわかると思います。 これをどうやって実現しているかというと、ViewController.mのcomboChange:(UIButton*) buttonをみてください。 ほとんどの処理は先ほどのanimChangeと同じですが、その外側に_collectionViewController.collectionView performBatchupdates:がついています。これがつくとセルまでちゃんとアニメーションしてくれる、というわけでした。 みんな大好きStackoverflowにもいくつか回答があるのですが、そこにたどり着くまでかなり苦労したので、ご参考になれば。
アバター
はじめまして、長沢です。 弊社では最近一部サービスでAWS および Ruby を利用しているのですが、 今回はAWSの AWS SDK for Ruby を利用して クロスアカウントアクセス をやってみようと思います。 簡単に クロスアカウントアクセスについての説明 クロスアカウントアクセスとは、一言で言うと、異なるAWSアカウントをまたいだリソースの操作を行う事ができる機能です。 クロスアカウントアクセスの方法は IAM Role の AssumeRole API を利用します。 IAM Roleを利用したクロスアカウント API アクセスの方法の詳しい説明は こちら この記事たちを読めば大体は分かります。 個人的に思った注意しなくてはいけないところ (個人的にはまったところ) は AMIユーザーでなければクロスアカウントアクセスは出来ない 認証先のIAM Role の Trust Relationships は適切に設定して権限を管理する と言ったところでしょうか。 の部分に関しては最初は気づかずに Role で AssumeRole をしようとしていて、下記のエラーメッセージが出ていました。 "Roles may not be assumed by federated users" 事前準備(Webコンソール上でクロスアカウントアクセスの設定) 最初にWebコンソールを利用してアカウントの下記のAWSの公式ブログにあるような設定をしましょう。(ここでの説明は割愛致します) Delegating API Access to AWS Services Using IAM Roles | AWS Blog また、こちらの サーバーワークス様のブログ も大変分かりやすいです。 早速やってみる 上記の事前準備の設定が済んだら、 2つのAWSアカウントA、Bがあって それぞれ S3バゲット “account-a-bucket”(アカウントA) 、 “account-b-bucket”(アカウントB) が作成されていたときに、 クロスアカウントアクセスの仕組みを利用して、 アカウントAの IAM User “homes” が、アカウントBのS3に対してRead Only 権限をもつ IAM Role “s3-viewer” としてふるまい、アカウントBのS3バゲット名を取得する といったようなことを実現するためのコードを書いてみます。 コードの流れを簡単に説明すると、 IAMユーザーのアクセスキー、シークレットキーを利用してSTSにアクセス sts.assume_roleのAPIを利用して Credentialを取得 取得したCredentialを利用してアカウントBにアクセス といった感じです。 ※ 利用したRubyは 1.9.3-p327 です。 ※ キーがシンボルのHashの記法が 1.8.x と少々異なりますのでご注意ください。 cross_account_access.rb require ' aws-sdk ' # 設定 AWS .config({ region : ' ap-northeast-1 ' , access_key_id : ' アカウントAのhomesユーザーのアクセスキー ' , secret_access_key : ' homesユーザーのシークレットキー ' , }) # AssumeRole対象のIAM Role のARN assume_role_arn = ' arn:aws:iam::{アカウントBのID}:role/s3-viewer ' # session名は任意の文字列 assume_role_session_name = ' homess3viewersession ' # S3オブジェクトの取得(アカウントA) s3_a = AWS :: S3 .new puts ' ===== Account A Buckets ===== ' # バゲット名を出力 s3_a.buckets.each do | bucket | puts bucket.name end puts # STSオブジェクトの取得 sts = AWS :: STS .new # AssumeRoleを呼び出し一時的な認証情報を受け取る assume_info = sts.assume_role( role_arn : assume_role_arn, role_session_name : assume_role_session_name, ) # 認証情報の上書き AWS .config({ access_key_id : assume_info[ :credentials ][ :access_key_id ], secret_access_key : assume_info[ :credentials ][ :secret_access_key ], session_token : assume_info[ :credentials ][ :session_token ], }) # S3オブジェクトの取得(アカウントB) s3_b = AWS :: S3 .new puts ' ===== Account B Buckets ===== ' # バゲット名を出力 s3_b.buckets.each do | bucket | puts bucket.name end puts 実行してみます $ ruby cross_account_access.rb ===== Account A Buckets ===== account-a-bucket ===== Account B Buckets ===== account-b-bucket うまくできているようです! 念のため、アカウントA,B それぞれの IAM Policy や Trust Relationship の設定を以下に記載いたします。 アカウント A の設定 IAM User “homes” の Policy (STSのAssumeRoleとS3の閲覧に権限をつけている) { "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "*" }, { "Effect": "Allow", "Action": [ "s3:Get*", "s3:List*" ], "Resource": "*" } ] } ちなみに、STSで AssumeRole しようとして、 もしそのRoleに対して権限がないときは下記のようなエラーが出ます。 A client error (AccessDenied) occurred: User: arn:aws:iam::{AのアカウントID}:user/homes is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::{BのアカウントID}:role/s3-viewer アカウント B の設定 IAM Role “s3-viewer” の Policy(S3の閲覧に権限をつけている) { " Version ": " 2012-10-17 ", " Statement ": [ { " Effect ": " Allow ", " Action ": [ " s3:Get* ", " s3:List* " ] , " Resource ": " * " } ] } Trust Relationship { "Version": "2008-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::{AのアカウントID(12桁)}:user/homes" ] }, "Action": "sts:AssumeRole" } ] } もし、上記のPrincipalの箇所が "Principal": { "AWS": [ "arn:aws:iam::{AのアカウントID(12桁)}:root" ] } としてしまうと、 そのアカウントの全ユーザーがデフォルトでアクセスできることになってしまうので注意が必要です。 株式会社ネクストでは、一緒に世の中をもっと便利に楽しくしたい仲間を募集中です。 主体的に楽しみながら仕事できる方からのエントリーお待ちしています! http://recruit.next-group.jp/
アバター
ガジェット大好き、カメラ大好きな非エンジニアです。 360度全天球カメラRICOH THETAを買ってみたので、品川オフィスと合わせてちょっとだけご紹介です。 THETAはスティク型のカメラです。両面に魚眼レンズが付いていて、1回のシャッターで空間をまるっと撮影できます。 手にフィットする形状で、95グラムという軽量さ。荷物が多いガジェット持ちにはうれしい配慮です。 撮影は中央のシャッターボタンを押すだけ。起動が早いので、シャッターチャンスは逃しません。これまたうれしい! iPhone/Androidアプリを使用すればリモート撮影することも可能です。 ということで、本日は品川オフィスのリモート撮影に挑戦したいと思います。 こんな感じTHETAを設置します。 そして、アプリのボタンをぽちっと押すと本体から「キュイン」と可愛い音が鳴ります。 撮影はこれで完了! 撮影した写真はアプリ上で楽しむことも出来ますが、専用のビューワーで共有することもできます。 専用のビューワーは、こんな風に自分のWebサイトに埋め込むことができます。 品川オフィス受付 - Spherical Image - RICOH THETA 専用のビューワーを使用せずに見ると湾曲したJPG画像ですが、ヘッドマウントディスプレイ「Oculus Rift」、3D空間を再現する「Photosynth」などでも楽しむことができます。 撮影画像には位置情報もつけられるので、ライフログなどを付けるのにも良さそうです。 品川フロントビル - Spherical Image - RICOH THETA 一眼の魚眼レンズで撮影して、切って、貼ってみたいな作業不要です。 解像度やISO感度などは一眼レフには遠く及びませんが、 なにせ手軽!楽しい!撮影したときには気づかなかった、自分が見えていない場所も映っていたりといろいろなシーンで活躍しそう。 ただ、残念な点がいくつかあります。 ファームウェアのアップデートがあることを期待しつつも、 セルフタイマーがなーーーいッ! 撮影用の専用リモコンが欲しいッ!!! などなど・・・。 あぁうちのエンジニアなにか開発してくれないかなぁ |д゚)チラッ とつぶやきつつ、本日も「キュイン」と撮影! RICOH THETA: https://theta360.com/ja/
アバター
さて、前回にReadとCreateをしたので、次はDelete、Updateをしましょう! ドキュメント更新 前回同様、Updateは、NSDictionaryを操作します。 簡単にいえば、ドキュメント内容をNSDictionaryで受け取って、中身を入れ替えてまたセットし直すという感じです。 まず、この時点で、UITableViewを配置している前提としています。 流れは ドキュメントをMutableDictionaryで受け取る Bool値を入れ替える CBLDocumentに値をputする という感じになります。 Couchbase LiteをCBLDocumentベースで更新 見て分かる通り、ほぼCreateと変わりません。 いうなれば、CBLDocumentを作成する時が、untitledなのか、documentWithIDなのかの差です。 ドキュメント削除 削除は簡単。 流れは 削除する対象のCBLDocumentを作成 CBLDocumentをdeleteする Couchbase LiteをCBLDodumentで削除 こちらもほとんど他のとやり方は変わりません。 まとめ CUDの流れは CBLDocumentを作成 putなりdeleteなりする Rは CBLQuery作成してDocumentを取得 イテレータでArrayに込めなおす って感じですね。 ここまでNSDictionaryで作成したりなんだりしましたが、次回はモデルを使った操作も見てみましょう。 株式会社ネクストでは、一緒に世の中をもっと便利に楽しくしたい仲間を募集中です。 主体的に楽しみながら仕事できる方からのエントリーお待ちしています! http://recruit.next-group.jp/
アバター
大坪と申します。12/4-6に高知で行われましたWISS2013に参加しました。2年前WISSについて私はこう書きました。 WISS の正式名称は「インタラクティブシステムと ソフトウェア に関するワークショップ」だが、誰もこの名前で呼びはしない。ほとんどの場合「ういっす」と呼ぶ。では WISS とは何か?公式サイト ( http://www.wiss.org/WISS2011/ ) には以下のような文字が並んでいる。 「WISS は、2泊3日の泊り込み形式で、インタラクティブシステムにおける未来を切り拓くような新しいアイディア・技術を議論するワークショップです。この分野において国内でもっともアクティブな学術会議のひとつであり、例年170名以上の参加者が朝から深夜まで活発で意義深い情報交換をおこなっています。」 しかし WISS に参加することの意味は、これだけの文字で語り尽くせるものではない。 via: WISS2011 参加報告 - 株式会社ネクスト エンジニアBlog WISSがどのような場か?ということについては、上記引用元を参照していただくとして、今年印象的だった点について書きます。 - WISSとはなにか?その答えは人によって違うでしょうが、今年特に記憶に残ったのはプログラム委員長五十嵐教授の 「WISS発表中に行う議論は、参加者全員によるブレーンストーミングのようなものだ」 でした。WISSはあくまでもワークショップ。完成した研究に「権威付け」を与えるような場ではなく、まだ未完成だが興味深いideaに関して議論を行い発展させていく場所である、と。 そう考えれば重要なのは「人と人とのコミュニケーション」である、という結論が導かれるわけです。しかしここに問題が。エンジニアとか「理系」と呼ばれる人の中には、コードやガジェットやコンピュータとコミュニケートすることは得意でも、対人コミュニケーションには二の足を踏んでしまう、という人も多いのではないでしょうか。(少なくとも私はそうです) しかしそうした「問題」を解決するのもテクノロジーの役割。宿泊を伴うカンファレンスで、食事の時どこに座るかは常に気を使う問題です。周りが知らない人ばかりだと何を喋っていいかわからない。しかし知り合いばかりで固まっていては進歩がない。こうした機会だから有名なあの人とお話したいけど勇気が出ない。 そうした問題に解決策を与えてくれるのが、去年から運用されている「夕食時席ぎめシステム」。事前に「こんな話題について語りたい」「◯◯さんとお話したい」「誰かと、誰かが一緒のテーブルになると面白いんじゃないか」という希望を登録しておけば、できるだけその要望に沿う形で夕食の席が決まる。とはいえ席について最初の数分は 「そもそもなぜこの顔ぶれになったのか」 で皆が悩むことになります。 今年もこのシステムには大変お世話になりました。二日目の晩に同じテーブルになったのは、神戸大学の西田准教授。彼はWISS2006で「遠くの3次元より近くの2次元」という言葉とともに大いに議論をよんだ「 萌え木;拡張現実による植物育成支援 」の著者であるとともに、夕食席ぎめシステムの開発者でもあります。西田さんからは「萌え」の心について大変興味深い話を聞かせてもらえました。話が盛り上がりすぎて、他の人達が夕食場から立ち去ったあともずっと居残り、ホテルの人たちにご迷惑をお掛けしてしまったのではないかと少し反省しております。 その後のナイトセッションでは、大学での情報系の教育の悩み、社会から期待されていることは何なのか。そもそもSEなる奇妙な職種の人はプログラムを一行も書かなくても、、とかそんな議論ができました。睡眠時間の確保に何よりも情熱を燃やす私が、(私にとっては)夜遅くまで話し込んでいた、というのは稀有の出来事です。 WISSは通常交通の便があまりよくない場所で開催されます。なぜかというと夜に外にでかけてしまうのを防止するためだとか昔聞いたような。今年は珍しく高知城から歩いて数分の便利の良い場所で開催されましたが、夕食後に抜け出してどこかに行こう、などという人はあまりいなかったのではないかと思います。というかもったいない。 - 前WISSプログラム委員長の後藤さんは朝一番 「皆さん。おはようございます!」 と凛とした挨拶で眠気を吹き飛ばしてくれました。プログラム委員長は代わりましたがこの「朝の挨拶」はちゃんと受け継がれているようです。その後には様々な分野の発表が続く。参加者は発表の間もチャットシステムを使って議論を行います。 昨今Twitterを利用してカンファレンスの参加者が議論することは珍しくありませんが、WISSのチャットはクローズドシステムということもあり、発現量が桁違いです。使われているのはシンプルなチャットですが、一点だけ特徴が。「これは同意」という発言に対して「同意ボタン」を押すとその発言が大きくなります。また最終日には「見たくない発言を小さくするボタン」が追加で実装されました。 過去には「2次元チャット」など様々なチャットシステムが使われたのですが、結局シンプルなテキストチャット+同意ボタンに収束してきた、というのは大変興味深い点です。 もう一つ発表時の試みで興味深いのは、外部へのインターネット接続制限です。人間はどうしても馴染みのある、居心地のよい環境に閉じこもりがち。発表を聞き質疑応答であるいはチャットで議論を交わすべき、とわかっていてもついFacebookを見てしまう、仕事のメールに返信をしてしまう、あるいは研究室独自のチャットシステムに引きこもってしまう。 そうした問題を解消するため、去年から登壇発表中は外部へインターネット接続ができなくなっています。これに対しては様々な議論が有り、例えばチャットでの議論に先行研究を参照したい、という要望に答えて、接続できる範囲が調整され続けています。 私はこの取り組みに基本的に大賛成しています。今から10年ほど前の「将来予想図」では「だれでもどこでもインターネット」が実現すればすばらしい未来が来る、と脳天気な絵が描かれていました。しかし現実はどうでしょう?どこにいてもSNSにアクセスし続けることが本当に「すばらしい未来」につながっているのでしょうか?誰かと話している時ですら、スマホの画面をいじり続けるのが我々が目指した未来でしょうか?情報技術がもたらす恩恵と問題のバランスに関しては常に問い直し、見直しをかける必要がある。これはそうした取組の一つとして大変意義あるものだと思います。 - 全ての日程が終了した後には非公式エクスカーション「沢田マンションツアー」が行われました。沢田マンションとはなにか? Wikipedia によれば 沢田嘉農 (さわだ かのう、 1927年 8月11日- 2003年 3月16日)は、高知県生まれ。幼少時に雑誌で見た「 アパート 」の様子に感動して、集合住宅の建築・経営を一生の仕事にすると思い定める。 via: 沢田マンション - Wikipedia 沢田嘉農氏の 「これはすごい。絶対これを作ってやる」 という思いは、WISS参加者の心情にぴったりではないか。マンションを設計したことも、建築した経験がなくてもとにかく作ってしまう。WISSでは常に新しい試みが実践され、かつ研究として発表される。つまり前例がないことが当然なわけです。前例や経験はなくても 「これがあるべきだ」 と考えれば作って発表し、それに対して皆が議論をする。沢田マンション屋上にある手作りクレーンにWISSでデモされていた数々の「手作りデバイス」のイメージを重ねあれこれ考えていました。 - じゃあお前は他人が作ったものについて議論をするためだけに行ったのか、と問われれば「いやデモ発表をしました」と答えます。おそらく日本で一番(世界でも有数かもしれません)UIやUXに関して意見を持っている人達相手にデモをするのは度胸のいることですが、「 へやくる! 」に実際に触っていただき議論をさせてもらいました。 物理的高さと言語の壁に挑む筆者 意見をいただけた方に感謝です。さて来年の開催場所はまだアナウンスされていませんが、WISSでの議論に貢献するためにはどんな方法があるか、今から頭を悩ませております。 =========================================== 株式会社ネクストでは、一緒に世の中をもっと便利に楽しくしたい仲間を募集中です。 主体的に楽しみながら仕事できる方からのエントリーお待ちしています! http://recruit.next-group.jp/
アバター
こんにちは、@nazomikanです この記事は(JavaScript - Client Side - Advent Calendar 2013)の15日目の記事です。 @teramako 妙な古臭さを感じるのだが…。 http://d.hatena.ne.jp/teramako/20131216/p1 と的確な斧をいただいたので記事を修正しています これまで標準化されていなかった __proto__ がES6で標準化されようとしています。 参考: draft_proto_spec_rev2.pdf (大変古かったので差し替えました。) 参考: Object.prototype.__proto__ ※ まだドラフトで確定ではないのでご注意ください。 Object.prototype.__proto__ Enumerable : false Configurable : true 内部変数のUnderscoreProtoEnabledの真偽によってこのプロパティの操作を追跡するかしないかを決定します。 UnderscoreProtoEnabledは Object.prototpye をもっていればデフォルトでtrueになります。 重要なのは __proto__ は Object.prototype 上にいると明言されるようになったこと と、 __proto__ の UnderscoreProtoEnabled の挙動が明言されたこと。 (Rev20 Oct 28 2013の時点で UnderscoreProtoEnabled の内部プロパティに関する記述が消えてました) 元となるのは この話 __proto__ 標準化の背景 我らが唯一神のDouglasのGood Partsにこんなコードがあった。 that.on = function (type, ....) { .... var registry = {}; .... if (registry.hasOwnProperty(type)) { registry[type].push(handler); } else { registry[type] = [handler]; } .... }; なんの変哲もないコードのように見えるがこのコードは本当の意味でセーフティではないのだ。 いちゃもんをつけるような話になりかねないのだが、例えばなんらかのモンキーパッチ(Object.prototypeへの変更を加えたりとか)によって registry が hasOwnProperty を持っていない可能性もある。 これは hasOwnProperty を uncurryThis で初期時に束縛していれば解決できる。 var uncurryThis = Function.prototype.bind.bind(Function.prototype.call) , hasOwn = uncurryThis(Object.prototype.hasOwnProperty) ; //... that.on = function (type, ....) { .... var registry = {}; .... if (hasOwn(registry, type)) { registry[type].push(handler); } else { registry[type] = [handler]; } .... }; ... はじめて見る人は面食らうかもしれないがちょっと前に(ここ) http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming で流行った安全なコードだ。 付録的に末尾に書いといたので興味があれば見てほしい。 とりあえず、 uncurryThis を用いたことによって、たとえ registry がモンキーパッチや Object.create(null) でhasOwnPropertyをもっていなかったとしても安全に動作するように変更できた。 これでこのコードは安全になったように見える。 しかし問題はまだあった。 ここからが本題で、 type という変数が関数の外から渡されてきていることに注目したい。 この type は hasOwnProperty によってのみバリデーションをされている。 そう、ここが論点なのだ。 話の流れ的に分かるかもしれないが type が __proto__ という文字列だったときに問題が起きる。 これまで __proto__ は特に標準化もしていなかったためにそれぞれのブラウザ間で以下のような場合に評価結果が異なってくるのだ。 [{}.hasOwnProperty('__proto__'), {}.__proto__.hasOwnProperty('__proto__')] false,false // Chrome true,true // WebKit Nightly false,true // FF Nightly false,false // Opera 12 alpha throws TypeError // IE10 Preview 2 (2011/12/26の時の話です) IEが __proto__ をサポートしてないがためにexceptionを発生させるが、そんなことは問題ではない。 ここで驚くのはWebKit Nightlyの挙動でしょう。 {}.hasOwnProperty('__proto__') の挙動がこのブラウザでだけ true を指し示している。 最初のコードをもう一度見直してみよう that.on = function (type, ....) { .... var registry = {}; .... if (registry.hasOwnProperty(type)) { //....(1) registry[type].push(handler); // ....(2) } else { registry[type] = [handler]; } .... }; 先ほどの実行結果を元に考えると type の値が __proto__ という文字列だった場合、(1)は if (registry.hasOwnProperty('__proto__')) { となり、Webkit Nightlyでのみ true を返すことになる。 これによって(1)を通過し、(2)を実行する時に registry['__proto__'].push(handler); となり、 __proto__ はobjectなので Object.prototype.push なんてもってないよとばかりにエラーを発生させるのだ。 とまぁ、こんなブラウザ間での挙動が引き起こした穴を埋めるため標準化が始まりました。 今後(といっても確定ではないが)、 __proto__ は Object.prototype 上にいると定義されるわけなので [{}.hasOwnProperty('__proto__'), {}.__proto__.hasOwnProperty('__proto__')] の実行結果は [false, true] に統一されていくのでしょう。 setPrototypeOf ここまで __proto__ 標準化の流れについて色々書きましたがES6からは Object.setPrototypeOf が定義されつつあるので __proto__ 系の操作はそちらを通して行われるほうが今後としてはよいようです。 @teramakoさんまさかりありがとうございました(^-^)/ おまけ( uncurryThis ) 以外と難しいので説明 obj.func1 func1において this の指す値は obj になる。 そう、つまりこの形において this とは . より左の部分を指す つまり var uncurryThis = Function.prototype.bind.bind(Function.prototype.call) は Function.prototype.bind の this を Function.prototype.call に変更している(= . より前を差し替えている)という風に言えるので Function.prototype.call.bind と等価だと言える。 さらにそれをふまえた上で var uncurryThis = Function.prototype.bind.bind(Function.prototype.call), hasOwn = uncurryThis(Object.prototype.hasOwnProperty); if (hasOwn(registry, type)) を見てみると var uncurryThis = Function.prototype.bind.bind(Function.prototype.call), // === Function.prototype.call.bind hasOwn = uncurryThis(Object.prototype.hasOwnProperty); // === Function.prototype.call.bind(Object.prototype.hasOwnProperty) // === Object.prototype.hasOwnProperty.call if (hasOwn(registry, type)) // === if (Object.prototype.hasOwnProperty.call(registry, this)) と等価であることがわかる。 こんな感じでcallのthisを束縛してモンキーパッチに対抗するみたいな方法のことです。 株式会社ネクストでは、一緒に世の中をもっと便利に楽しくしたい仲間を募集中です。 主体的に楽しみながら仕事できる方からのエントリーお待ちしています! http://recruit.next-group.jp/
アバター
こんにちは上津原です。 今回はUnityネタです。 現在Unity3Dを触っているのですがやっと面白くなってきました! そしてそこで、調べてなかなか出てこなかった「一人称視点でモノを浮き上がらせて移動させる方法」について書いてみようと思います。 具体的に説明すると こんな風に下に落ちているオブジェクトを こんな風に中心点で維持して持ち上げる方法ということになります。 調べてみると、方法は2種類ありました。 MainCameraをParentにする方法 FiexdJointを活用する方法 それぞれ紹介していきます。 MainCameraをParentにする方法 対象となるオブジェクトを、カメラのParentに指定して、グルーピングしてしまう方法です。 コードは以下のようになります。 ※動かす対象に「Target」タグをつけています。 Unityでモノを持ち上げ、離す。左クリックで物体をとらえ、 左クリックで落とす、右クリックで投 ... 上記ソースは、ついでに持ち上げた時に右クリックすると前方に投げるファンクションも含まれています。 この方法の特徴 モノを持ち上げて移動しているとき、その場から動かない設定をしているオブジェクト、またはリジットボディを設定していないモノにぶつかった場合、コリジョンを無視する結果となります。 動かすことにできるものにぶつかった場合は、Massを無視してあたったシテを移動させます。 持ち上げている物体がすり抜けてしまう、というわけです。 なので、その方が都合がいいぞ、という場合はこちらを利用するといいかもしれません。 FiexdJointを活用する方法 対象となるオブジェクトとカメラをPhysicsの機能である「Fixed Joint」でつないでしまう方法です。 こちらの方法は、上記方法と違い、モノをすり抜けずにあたり判定をきちんと保って移動させることができます。 実装はは以下のようになります。 まず、MainCameraにPhysicsの中にある、FixedJointを追加します。 FixedJointを追加すると、勝手にRigitBodyが追加されます。 「Mass」を適当な値にし、 「Is Kinetic」にチェックを入れます。 これを入れないとカメラが落ちて行ってしまうので気を付けてください。 そしてコードは以下のようになります。 あたり判定を保ったままオブジェクトを移動させる。 こちらのソースは、前方に投げるアクションはついていません。 この方法の特徴 前述しましたが、持ち上げたもののあたり判定を保ち続けることができます。 Massのことも考慮され、重いものを動かすことはできないし、軽いものは動かすことができます。 そして通り抜けられないモノにあたるとブルブルしてちょっと怖い結果にはなります。 まとめ 物理の法則を考慮する必要がないならParentに! 考慮する必要がないのならFixed Jointがいい! という考えに落ち着きました。 どっちを使うにせよ、こんなにお手軽に実装できてしまうのがすごい。Unity恐るべし。 株式会社ネクストでは、一緒に世の中をもっと便利に楽しくしたい仲間を募集中です。 主体的に楽しみながら仕事できる方からのエントリーお待ちしています! http://recruit.next-group.jp/
アバター
jadeを知る
こんにちは、@nazomikanです (この記事はNode.js Advent Calendar 2013の10日めの記事です) nodeでテンプレートエンジンといえばjade その一方で公式ドキュメントで書かれていることだけではだいたい痒い所に手が届かないのでissueから拾い集めたノウハウとか将来的な話とかを書きます 属性の存在が条件によって分かれるケースの書き方 url が存在するときdata-url属性をつける //truthy: <p data-url="xxx"> //falsy: <p> in jade: p(data-url=(url ? url : false)) 属性の値が条件によって分かれるケースの書き方 bool がtruthyの時は class="is-show" を、そうでない時は class="is-hide" をつける //truthy: <p class="is-show"> //falsy: <p class="is-hide"> in jade: p(data-url="is-#{bool ? 'show' : 'hide'}") 子要素にテキストとDOM要素が並列に存在しているケースの書き方 <p> この商品は<span class="price">10,000</span>円です </p> in jade: p | この商品は span.price 10,000 | 円です エスケープしたい変数とエスケープしたくない文字列が混在してる時の書き方 <p> この部屋の広さは#{space}m&sup2です </p> in jade: p | この部屋の広さは#{space}m != &sup2 | です if/elseで出し分けた要素の子要素を記述したい時の書き方 // bool is true <p> <a href="#"> <img src="./hoge.jpg"> </a> </p> // bool is false <p> <span> <img src="./hoge.jpg"> </span> </p> in jade(うまくいかないケース1): p if bool a(href="#") else span img(src="./hoge.jpg") -> elseの時だけしかでない in jade(うまくいかないケース2): p if bool a(href="#") else span img(src="./hoge.jpg") -> pの直接の子要素になる in jade(うまくいかないケース3): p if bool a(href="#") else span img(src="./hoge.jpg") -> elseの時にspanの兄弟要素として出る end とかないのでこの辺は mixin を使うしかない in jade(正攻法): mixin wrap(bool) if bool a(href="#") else span p +wrap(bool) img(src="./hoge.jpg") こんな荒業もある p #{bool ? 'a': 'span'} img でもこれは属性かくのうまくできないので辛い また、 | で続く文字列がプレーンなテキストになるのを利用して単純に開始タグと閉じタグで挟むという方法もあるにはある if bool | <a href="#"> else | <span> #inner-div if bool | </a> else | </span> 個人的にはラップしたいタグの階層が同じ場合は #{bool ?'a(href="#")' : 'span'} で済ませて、階層がごっそり違う場合はmixinを使うようにしてる 動的にインクルードしたい時の書き方 inclide ./#{foo}.jade みたいなことをしたいと誰しもが夢を見るが現在のところカスタマイズ無しでは無理 caseを用いて泥臭くやるしかない in jade: case foo when 'a' include a.jade when 'b' include b.jade //- ... checked=checkedとかdisabled=disabledとかを条件に応じて出し分けたい時の書き方 // bool is true <p checked="checked"> // bool is false <p> in jade: p(checked=bool) data-*にjsonを流し込みたい <p data-person={"name":"nazomikan"} in jade: - var person = JSON.stringify({name: "nazomikan"}) p(data-person="#{person}") inlineのブロックを使いたい時 インラインのブロックを使いたいこともあるでしょう タグの宣言後に : を使えばネストしたタグがかけるのでそれを利用してblockも書きましょう parent.jade h1: block article_title child.jade include parent block artiicle_title | awesome article 親ブロックの中身を継承したい時の書き方 parent.jade block contents p parent child.jade include parent block contents p child とあった時、評価結果は以下のようになる <p>child</p> これを <p>parent</p> <p>child</p> といった感じで親のブロックの中身を継承したいときは block append xxx を利用する parent.jade block contents p parent child.jade include parent block append contents p child とすると <p>parent</p> </p>child</p> が得られる また、前に挿入したいときは block prepend xxx で実現できる 実は yield が使える langage referenceには記載されてなかったけど平然と yield キーワードをサポートしている includeと組み合わせることで使える main.jade div include partial li main side partial.jade ul yeild li partial side1 li partial side2 とすることで以下のような結果を得ることができる <div> <ul> <li>main side</li> <li>partial side1</li> <li>partial side2</li> </ul> </div> タグの圧縮を解除したい場合 基本的にjadeではデフォルトでタグが下記のように圧縮されるようになっている <!DOCTYPE html><html><head><title>Express</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><p>Hello World</p></body></html> これをインデントのついた状態に表示したいときは以下のようにする 生のjade var html = jade.render('jade string', { pretty: true }); in Express(v3.x) app.locals.pretty = true in Express(v2.x) app.configure(function(){ app.set('views', dirname + '/views'); app.set('view engine', 'jade'); app.set('view options', { pretty: true }); // <- here app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(dirname + '/public')); }); パフォーマンスを上げる jadeは現時点のデフォルト設定で十分に高速なテンプレートエンジンですが設定と実装次第ではさらに高速化させることができます namespaceを導入する jadeは通常以下の手順でコンパイルされます var fn = jade.compile("p #{title}", {}); fn({title: 'Title'}); template文字列の中で title という変数でアクセスできてますが、オブジェクト渡ししてるのに、なぜ xxx.title という形じゃないのか不思議ですね それは内部的に with 構文を利用してオブジェクトプロパティの変数展開をおこなっているからです ある程度jsに精通している方ならわかると思いますが with は構文内で与えられたオブジェクトのプロパティを変数に展開できるという機能があり、それまでの処理内容によって展開される変数に変化がおこるという動的スコープの性質をもっています これは実行前最適化に対して非常に厄介な問題で with 構文が処理中に含まれているとその部分に対して最適化が行えなくなります この問題を解決するためのオプションが self: true です このオプションを設定するとテンプレート内で self.title という形で変数にアクセスできるようになります 常に self という名前空間を通して変数にアクセスすることによって with 構文を回避できるというものです これを踏まえて先ほどの処理を書き換えると以下のようになります var fn = jade.compile("p #{self.title}", {self: true}); fn({title: 'Title'}); 結構中の人的には絶賛されてる機能みたいです tj: I like self muuuuch danielbeardsley: This is a crazy performance increase: 490ms -> 27ms Running the benchmarks shows jade-self takes 27ms, where jade takes 490ms. The fastest non-jade templating engine was ejs and it ran the test in 89ms. Go Jade! この ベンチ のことだと思います かなり高速化されてますね ejsと比べても数倍早いみたいですね compileDebugを本番時に切る jadeにはデバッグ用に compileDebug というオプションがあります これを切ると単純にデバッグ用にとってた情報をとらなくなるので早くなります といっても最低限の最低限の情報は出るので安心ください エラーログを見比べてみましょう 適当なファイルで参照エラーを出してみたときのエラーです わざと間違えたコード - var title = self.title h1= title p Welcome to #{sel.title} //- ここが間違い sel -> self compileDebug: true 500 ReferenceError: /home/nazomikan/node_workspace/jade_test/views/index.jade:10<br/> 8| - var title = self.title<br/> 9| h1= title<br/> > 10| p Welcome to #{sel.title}<br/> 11| <br/> 12| <br/><br/>sel is not defined at ....(以下コールスタック) compileDebug: false 500 ReferenceError: sel is not defined at ....(以下コールスタック) compileDebug: true の時は中のテンプレートも文字列まで表示してくれてるようになってます 開発時は true , 本番時には false にして切ってしまうのが推奨されています 将来のことを考える jadeはこんなにも普及してる一方でまだメジャーバージョンではないという反面もあります。(2013/11時点でv0.35.0) まだ用意されているsyntaxの中で廃止や追加がかなりの数、検討されています。 以降の項目を確認しましょう !!! はv1.0.0で消滅する html2jadeとかで <!DOCTYPE html> <html> </html> と打ち込むと !!! 5 と変換されますがこのsyntaxは廃止されますので注意が必要です 書きやすい反面、jade初学者には大変読みづらいという意見がでて廃止に至りました 参考 もともと !!! は doctype のエイリアスなのでこう書くのが将来的にも生き残る書き方になります doctype 5 代入構文( - 無し)が削除される 今まで、 (1) - var a = 1 - var b = 2 a = b span #{a} みたいな感じで書くと <span>2</span> って感じに評価されていたのですがこの a = b という代入演算子が使えなくなります 下記のように - を前につけてあげるとこれからも使えます (2) - var a = 1 - var b = 2 - a = b span #{a} これはjadeからjsにコンパイルされたときの状態に問題があったため削除されることになりました - ありであれば式はそのまま評価されます (1)を評価すると以下のようにjsに変換されます function anonymous(locals) { var buf = []; var a = 1; var b = 2; var a = b; { buf.push("<span>" + jade.escape((jade.interp = a) == null ? "" : jade.interp) + "</span>"); } return buf.join(""); } var a = b となって二重定義されていることに注目してください (2)を評価すると var a = b の部分が a = b と評価されます これは以下のようにスコープのネストが発生した場合に問題を起こします mixin parent() div block mixin check(value1, value2) +parent unless value2 value2 = value1 | value1 = #{value1}, value2 = #{value2} +check(1, 2) これは value1 = 1, value2 = 2 を期待した処理ですが実際には value1 = 1, value2 = 1 と解釈されます なぜならこの処理は以下のようにjsに評価されるからです function anonymous(locals) { var buf = []; var parent_mixin = function() { var block = this.block, attributes = this.attributes || {}, escaped = this.escaped || {}; buf.push("<div>"); block && block(); buf.push("</div>"); }; var check_mixin = function(value1, value2) { var block = this.block, attributes = this.attributes || {}, escaped = this.escaped || {}; parent_mixin.call({ block: function() { if (!value2) { var value2 = value1; // ここに注目 } buf.push("value1 = " + jade.escape((jade.interp = value1) == null ? "" : jade.interp) + ", value2 = " + jade.escape((jade.interp = value2) == null ? "" : jade.interp) + " "); } }); }; check_mixin(1, 2); return buf.join(""); } check_mixin 内の parent_mixin 呼び出し時の block のスコープの中で var value2 = value1 と評価された式があります この block のスコープ内では value2 はスコープチェインを通して check_mixin の引数の value2 を参照したいのにここで var 宣言されたことによって、このスコープ内でhoistingが発生し、一つ上の if (!value2) { の式の value2 が undefined になります そのため、評価されない予定だった var value2 = value1 が評価されてしまう結果になります ちなみに - をつけて以下のように書くと mixin parent() div block mixin check(value1, value2) +parent unless value2 - value2 = value1 | value1 = #{value1}, value2 = #{value2} +check(1, 2) jsに以下のように変換されます function anonymous(locals) { var buf = []; var parent_mixin = function() { var block = this.block, attributes = this.attributes || {}, escaped = this.escaped || {}; buf.push("<div>"); block && block(); buf.push("</div>"); }; var check_mixin = function(value1, value2) { var block = this.block, attributes = this.attributes || {}, escaped = this.escaped || {}; parent_mixin.call({ block: function() { if (!value2) { value2 = value1; //ここに注目 } buf.push("value1 = " + jade.escape((jade.interp = value1) == null ? "" : jade.interp) + ", value2 = " + jade.escape((jade.interp = value2) == null ? "" : jade.interp) + " "); } }); }; check_mixin(1, 2); return buf.join(""); } この場合は value2 = value1; に var がついていないためhoistingが発生せず意図した value1 = 1, value2 = 2 という値が得られます こういった複雑な問題から - 無しで記述される代入構文が削除されます クライアントサイドでのjadeの利用においてIE8以下のサポートがなくなる クライアントサイドでjadeを利用してますっていう声はあまり聞きませんが、サポートがなくなるそうです 古いブラウザに対する狂気じみた対応のせいで全ブラウザでのパフォーマンスが劣化するのにはもうやめだ モダンブラウザこそが真にサポートされるべきなんだ! みたいな感じのようです 株式会社ネクストでは、一緒に世の中をもっと便利に楽しくしたい仲間を募集中です。 主体的に楽しみながら仕事できる方からのエントリーお待ちしています! http://recruit.next-group.jp/
アバター
秋山です。 「littleBits」という気軽に電子工作が楽しめるガジェットがあります。 littleBits(リトルビッツ) littleBits は、様々な機能をもったモジュールがあり、それらをつなげることで特定の動作を楽しめるものです。 モジュール同士をつなぐには両端についている磁石でつなぐので非常に簡単ですし、間違った接続をしようとすると磁石が反発しあうので、知識のないお子様でも色々な電子工作ができるようになっています。 今回は少しだけどんなものか紹介します。 こんな箱に入ってきました。 先日、facebookで35%offのクーポンを配布していたので、勢い余ってDelux Kitを購入しました。 すでに持っていた知人からもモジュールは多いほうがいいよ、とアドバイスもらったので、そりゃそうか。多いことはいいことだ。と迷うこと無くDeluxをカートに投下。 海外発送なのですが、注文から3日で届くスピード出荷! さっそく中を開けるとモジュールびっしり。 子供に扱いやすくするためか思ったより小さく、カラフルで見てるだけでワクワクしてきますね。 ということで、眺めていてもしかたがないので軽く動かしてみましょう。 電源は基本的に付属の9V形電池を使用します。 それと、Powerモジュールを接続することで電源供給ができるようになります。 さっそくRGB LEDモジュールを使ってLEDを光らせてみます。 おわかり頂けただろうか… LEDが点灯していることを。 このLEDは今は点灯しっぱなしです。 PowerモジュールとRGB LEDモジュールの間に、Pulseモジュールを挟んでみます。 おー、LEDが点滅し始めました。 簡単ですね。 では次はServo motorモジュールを使って、動くものを作ってみましょう。 RGB LEDモジュールをServo motorモジュールに変えるだけです。 うん、これも簡単。 こんな感じに安心・安全・簡単に電子工作を楽しむことができます。 ダンボールや3Dプリンターなどを使って車を作ったり、ピタゴラスイッチのようなものを作ったり、色々と楽しめそうです。 littleBitsは年末年始、暇をしてるあなたにピッタリなガジェットではないでしょうか。 私はこれで年を越せそうです。 =========================================== 株式会社ネクストでは、一緒に世の中をもっと便利に楽しくしたい仲間を募集中です。 主体的に楽しみながら仕事できる方からのエントリーお待ちしています! http://recruit.next-group.jp/
アバター
ネクストにもOculus Riftがやって来ました! Oculus Riftとは http://www.oculusvr.com/ OculusVR社が開発中のバーチャルリアリティヘッドマウントディスプレイです。 6軸ヘッドトラッキング機能がついていて、首を右に向ければ右を見れるし、上を見れば上を見れる。 視野角も非常に広く高い没入感を得られます。 早速なので、Unity上で開発環境を作ってみましょう。 ※Oculus Rift SDKを動かすにはUnityProが必要です。 1.Oculus Riftデベロッパー登録 まずはデベロッパー登録をします。 https://developer.oculusvr.com/ 必要事項を入力し、登録します。 登録にはお金はかからないのでご心配なく。 2.SDKのダウンロード&インポート Unity 4 Pro Integration をダウンロードします。 そのファイル展開すると以下のようになります。 次に、Oculusに対応したいUnityプロジェクトを開き 先ほどダウンロードしたディレクトリの OculusUnityIntegration/OculusUnityIntegration.unitypackage をダブルクリックします。 そうすると、unityへ必要ファイルのインポートが始まります。 3.プロジェクトをOculusに対応 インポートされた OVR の中にある、Prefabs/OVRPlayerControllerをSceneにドロップすれば完了です。 ゲーム画面が2画面に分割されます。 あとは、BuildすればOK!とっても簡単ですね〜。こんなに簡単にVRの環境ができちゃうとは、すごい。 ============================================== 株式会社ネクストでは、一緒に世の中をもっと便利に楽しくしたい仲間を募集中です。 主体的に楽しみながら仕事できる方からのエントリーお待ちしています! http://recruit.next-group.jp/
アバター
さて、前回ビルドまで完了したので、今回は早速、データの作成、保存。 そして読み込みをやってみましょう。 CouchbaseLiteは、JSONドキュメントが基本です。 なので、データ自体も連想配列形式で作成します。というわけでNSDictionary形式でデータを作ります。 ViewController.mに以下のコードを追加していきます。 ドキュメント作成 流れ的には以下のようになります。 1.連番を作る ※CouchbaseLiteにはドキュメントを表すユニークなIDを作る機能はありますが、連番を作る機能はありません。 2.新規にのドキュメントを作成する 3.ドキュメントをデータベースにPutする // 新規ドキュメントの作成 - ( void )createDocument{ // Appdelegateを呼ぶ AppDelegate *ap = (AppDelegate *)[[UIApplication sharedApplication] delegate]; // カウントの読み込み NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults]; // カウントが0だったら1にする // ※連番を作る機能がないので、ここで作成する int num = [userDefault integerForKey:NUMBER_KEY]; if (num == 0 ) { num = 1 ; } // カウント文字列の作成 NSString *numberStr = [NSString stringWithFormat: @" %d " ,num]; // ドキュメントを追加 NSDictionary *contents = @{ @"text" : numberStr, @"check" : [NSNumber numberWithBool:NO], @"created_at" : [CBLJSON JSONObjectWithDate: [NSDate date]]}; // 無記名ドキュメントの取得 CBLDocument* doc = [ap.database untitledDocument]; // ドキュメントの追加 NSError* error; if (![doc putProperties: contents error: &error]){ // 失敗したらアラートを表示 [ self showErrorAlert: @"Couldn't save the new item" ]; } else { // 成功したらカウントを上げる NSLog( @"Save Complete!" ); + +num; // ユーザデフォルトのに保存 [userDefault setInteger:num forKey:NUMBER_KEY]; [userDefault synchronize]; } } // 失敗時のアラート表示 - ( void )showErrorAlert:(NSString *)message{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @"Error" message:message delegate: nil cancelButtonTitle: @"OK" otherButtonTitles: nil , nil ]; [alert show]; } CBLDocument: ひとつのデータを指します。一枚のJSONと考えて貰えれば一番わかりやすいかと。 ドキュメントそれ自体ではあるが、自身の保存、更新、削除機能もこのオブジェクトに入っています。 ここで注意する点は、databaseを使ってカラのドキュメントを作成する点です。 普通に考えると、CBLDocumentをnewすればいいんじゃ?となりますが、CBLDocumentそれ自体がPutする機能を持っておりかつ、CBLDocumentのdatabaseプロパティはReadOnlyなので後からセットすることができません。 なので、databaseと関連付けるためにdatabaseを使ってCBLDocumentを作成するというわけです。 余談:はじめDocument作って、Databaseに渡すという構図を想像してたのでチョビっとハマりました。 ドキュメントの読み込み そして次に、読み込みをしてみます。 コードは以下のようになります。 1.データを保管するArrayを作成 2.すべてのデータを読み込むQueryを作成 3.Arrayに取得したドキュメントを追加 @implementation ViewController { NSMutableArray *dataArray; //CBLデータを格納するArray } - ( void )viewDidLoad { [ super viewDidLoad]; // 格納配列の初期化 dataArray = [[NSMutableArray alloc] init]; //Documentを作成 [ self createDocument]; // すべてのDocumentを読み出す [ self loadAllDocuments]; } - ( void )loadAllDocuments{ AppDelegate *ap = ApplicationDelegate; // ArrayをClear [dataArray removeAllObjects]; // すべてのクエリを読み込む CBLQuery *allQuary = [ap.database queryAllDocuments]; for (CBLQueryRow* row in allQuary.rows) { // document取得 CBLDocument* doc = [ap.database documentWithID: row.key]; NSDictionary* contents = doc.properties; // data 追加 [dataArray addObject:contents]; } // 時間順に並び替えをする NSSortDescriptor *sortDispNo = [[NSSortDescriptor alloc] initWithKey: @"created_at" ascending:NO]; NSArray *sortDescArray = [NSArray arrayWithObjects:sortDispNo, nil ]; [dataArray setArray:[dataArray sortedArrayUsingDescriptors:sortDescArray]]; NSLog( @" %@ " , dataArray); } CBLQuery CouchbaseLiteを操作するQueryオブジェクト。 データベースで言うと、このオブジェクトにSQLを渡せばその結果がこのオブジェクト内に生成されます。 後に出てくるView機能などもこのCBLQueryを利用します。 ここでは、予め実装されている全ドキュメントを呼び出すクエリ「queryAllDocuments」を使って、全ドキュメントを取得するCBLQueryを作成しています。 CBLQueryRow CBLQuery内には、rowsというプロパティ内にクエリの結果が生成されておりその中のエンティティ的な立ち位置。 これらを実行すると、コンソールに今データベースに入っているドキュメントデータが表示されます。 起動時に1度しか追加していないので、1個しか出ないかと思います。 たくさん表示したい場合は何度か起動するか、for文でも作って回して貰えれば。 ここまでくれば、データはNSDictionaryが入ったArrayになっています。 Arrayに入っちゃえばもうこっちのもん!好き勝手利用できるようになります。やったね! では今日はこれくらいで、次回には削除、更新をしようと思います。
アバター
株式会社ネクストの花多山です。 前回の記事 海外研修 北欧に行ってきたよ - 株式会社ネクスト エンジニアBlog で 社内制度のひとつである「選抜海外研修」について触れましたが、 今回は現在開催中の制度である「クリエイターの日」について紹介したいと思います。 このクリエイターの日とは何かと言いますと、 クリエイター(エンジニア、デザイナー、プランナー等)が通常業務の枠を離れて、新たな技術やサービスの探求に取り組むことができる制度です。 希望者は四半期ごとに最大で7日間(年間合計で最大28日)合宿形式で研究・開発を行います。 某企業の20%ルールのネクスト版と言ったら分かりやすいでしょうか。 これまでクリエイターの日から生み出されたプロダクト(といっても一部になりますが)は、以下のサイトからご覧いただけます。 クリエイターの日 ただいま、第3四半期(10月~12月)の合宿期間中で、今回は11チーム(約30名)が鋭意活動中です。 活動中の風景をいくつか紹介してみましょう。 Node.jsチーム。ただいまリーダーW君(新卒2年目)の説教タイム中。 UI・UXにこだわったiPhoneアプリを開発中のようです。 黙々と作業をしておられます。 ただいま、Couchbase Liteの調査中とのことです。 お絵かきをしてますね。いったい何ができるんでしょうか? とまあ、各チーム自由なスタイルで最大7日間の合宿活動を頑張っております。 この後は、12月に社内で成果報告会を実施する予定で、どんな発表があるのか、今から楽しみにしています。
アバター
弊社(株式会社ネクスト)では、年に1回社内から7~8名程度の選抜メンバーで海外研修に行くイベントがあります。 選抜されるのは、営業や技術はもちろん、マネージャーから全社員が対象になります。 この海外研修ではある程度の金額を元に「 自分たちで行き先を決める 」という形です。 あまり他の会社では聞かない、面白い取り組みです。 海外研修は第3回で、私サムも参加することができました。 少しでも弊社(株式会社ネクスト)のことを知って頂ける機会になると思いますので、今回は海外研修について記事を書きます。 まずは、弊社がなぜこのような取り組みをおこなっているのか、その目的です。 目的① 世界視点の醸成 世界で何が起こっているか?をその目で見て、感じて、くること。その中で自分たちは何をすべきか? 目的② 部門を超えた交流の醸成 通常の業務以外でのコミュニケーションを濃密なものにし、研修の機会を通してより結束力の高いチームワークを構築する。 目的③ 成長機会の提供 この研修が皆さんの成長機会となり、個人・組織にとってより大きなフィードバックを生み出すことを期待します。 第1回、第2回と研修先がアメリカでした。 第3回目である私たちは、 スウェーデンとフィンランド に行ってきました。 まずはスウェーデンから、日本からおよそ13時間 基本的には、電車と徒歩がメインで、現地のコーディネーターさんにお願いして、色々な企業や場所を訪問するのが海外研修です。 訪問先も自分たちであらかじめ決め事前にアポを取るか、コーディネーターさんにお願いしていました。 弊社(株式会社ネクスト)は、 日本最大級の不動産・住宅情報サイト「HOME'S」 を運営しております。 そのため、住宅なども見に行ったりしました。 こっちの方は、ベランダや内装がおしゃれでした。 本屋でも、インテリアの雑誌がコーナー全体に揃っているくらいです。 訪問と訪問の間に色々と見回ることもできました。 また、研修期間中は休日を含んでいることから、土曜日日曜日は終日自由時間です。 フィンランドでは、女性経営者の朝会「 business in heart 」に参加してきました。 次に、当時のことをbusiness in heartもブログに載せてくださいました。 http://businessinheart.se/nyhet_allman/business-in-heart-far-en-kusin-i-tokyo/ 食事のレストラン決めから予約まで全部自分たちで 日程は全部で11日間だったのですが、途中で和食が恋しくなりました。 場所や企業だけでなく、有名なARABIAの工場も見学へ 筆者はアングリーバードのコップを買いました。 フィンランドの経済省と連携している vigo プログラム へ訪問 働き方や、目的など、さまざま事を勉強しました。 さらには、地元の大学へ ここでは産学協同に近い「 Startup Sauna 」というのもあり、そちらにも訪問しました。 このように、弊社(株式会社ネクスト)では、さまざまなイベントを行っております。 また、機会がありましたら、別のイベントも紹介できればいいと思います。 最後に こんな感じで楽しい海外研修でした。
アバター
株式会社ネクストの秋山です。 この度、弊社のブログにて公開しましたiOS7に関する記事に、NDAに抵触する内容が含まれていた為記事を非公開に致しました。 ご指摘頂きました KishikawaKatsumi 様、ありがとうございました。 今後はこのような事が無いよう、再発防止に努めてまいります。 今後とも、株式会社ネクスト エンジニアBlogを宜しくお願い致します。
アバター
上津原です。 前回は、Couchbase Liteの概要をお伝えしました。 今回は、実際に動作させていこうと思います。実際に動作させる私の環境は以下です。 Mac OS X 10.9 (Mavericks) Xcode 5.0.1 iOS7 先に断っておきますと、特にこの環境でないと動かせないわけではありません。Couchbase Liteのページでの動作環境は以下のようになっています。 Xcode 4.6 or lator iOS SDK 6.0 or lator ですので、ご自身の環境にあったものを使ってください。 ただし一部、Xcode5.xでプロジェクトを作成するか、Xcode4.6でプロジェクトを作成するかで設定が違います(後述) プロジェクト作成 新規プロジェクトを作成します。 テンプレートは「Single View Application」を選択します。 (もちろんこれも好きなものを選んで頂いても大丈夫です) Product Nameは「CBL_EXAMPLE」とし、DeviceはiPhoneを選びます。 その他の項目はお好きな様に設定してください。 Couchbase Lite Framework を追加する まずはこちら( http://www.couchbase.com/communities/couchbase-lite )から最新版のCouchbase Lite Frameworkをダウンロードします。 2013/11/18 時点ではcouchbase-lite-community-ios_1.0-betaが最新です。 ダウンロードしてきた、「CouchbaseLite.framework」をプロジェクトの「Frameworks」ディレクトリに追加します。プロジェクトにコピーを追加するかどうかはお好みでどうぞ。私は追加して動かしています。 次にBuild Settingsの「Other Linker Flags」に「-ObjC」を追加します。 そして最後に「Build Phases」の「Link Binary With Libraries」から、以下を追加します。 CFNetwork.framework Security.framework SystemConfiguration.framework libsqlite3.dylib libz.dylib ここで一旦エラーが出ないか確認するためにビルドをしてください。 ここで、Xcode5でプロジェクトを作成した人は警告が出るはずです。Xcode4.6の人は出ないはずです。 Xcode5でCouchbase Liteを動かすには? 現状のCouchbase Liteは、arm64に対応していません。 ですので、Xcode5の人は「Build Settings」の「Architectures」の項目を「Standard Architectures (including 64-bit)(armv7, armv7s,arm64)」から「Standard Architectures (armv7,armv7s)」に変更してください。 そうすればビルドの警告が消えるはずです。 Couchbase Lite を動かしてみる ビルドが通ればあとは実装してゆくのみです。 AppDelegateに以下を追加します。 #import <CouchbaseLite/CouchbaseLite.h> 次にプロパティ宣言を追加します。 @property (strong, nonatomic) CBLDatabase *database; そして、application:didFinishLaunchingWithOptions:に以下を追加します。 // CBLManager の作成 CBLManager *manager = [CBLManager sharedInstance]; // データベース作成 NSError *error; self .database = [manager createDatabaseNamed: @"my-database" error: &error]; データベース名に利用可能なのは、小文字[a〜z]、数字[0-9]、および特殊文字[$_()+ - /]となっています。 これでビルドが通る。 ここまでできれば、ビルドが通るようになっているはずです。 ビルドが完了すれば、アプリ内にデータベースが作成されます。 次回は、CRUD周りを見て行きたいと思います。
アバター
大坪と申します。さてiOS7専用アプリ「 へやくる! 」を開発して考えたことシリーズ(シリーズだったのか)第二弾(第一弾はなんだったのか)   iOS7での変更点、新機能は数多いですが今日はその中で特に「デザイン」(その定義がなんであれ)に関する点について。   iOS6までの実在の材質を模した意匠はiOS7ですっぱり消えました。それは時々「フラット」という言い方をされるわけですが、iOS7の基本的なDesign Principlesには「フラット」という言葉はありません。その代わり逆の意味を持つであろうDepth(深さ)という言葉が入っている。ではDepthとは具体的に何なのか?     それは画面が複数レイヤーから構成され奥行きを持っていることを知らせるため半透明の画面を使用することだったり、あるいはトップ画面のようにユーザがデバイスを持つ角度によって微妙に動きを見せることによってあたかもアイコンが浮かんでいるように見せること、と理解しています。   iOS6までは最初にJobsがOS Xを紹介した時に使った「人々が舐めたくなるようなボタンをデザインした」という言葉に代表されるこんな意匠を使っていたわけです。     こうした意匠は一見立体的であるかのように見え、深みを感じさせる、と言いたくなります。しかしそれは「まやかし」にすぎない。意匠は静的な画像であり、人々がそれに慣れてしまえばそれまでです。iOS6でのメモ帳は現実のNotepadを非常に精巧に模した意匠を持っていましたが、使っているうちそうした「工夫」はユーザの意識から消え、単なるコンピュータ上の「簡易エディタ」としてだけ使われます。   私の考えではiOS7でAppleは「静的な深さ」から「動的な深さ」に方向を変えたのではないかと。一番大切なのはユーザに見せたいコンテンツ。ボタンなどそれ以外の静的な意匠はシンプルなものにし、単独では確かに「フラット」に見える。しかしそれが「動的」に動くことによりユーザに深さを感じさせるようにした、と。   あるインタビューでIveはこう語っています。   One of the things that we were interested in doing is, despite people talked about this being “flat,” is that it’s very, very deep. It’s constructed and architected visually and from an informational point of view as a very deep UI, but we didn’t want to rely on shadows or how big your highlights could get.    引用元: Apple's Jonathan Ive and Craig Federighi: The Complete Interview   Iveの言葉は私にとって訳すのが難しいのですが、おそらくこんな意味かと 我々がやろうとしていること-”フラット”という言われ方をすることが多いが-はとてもとても深いものだ。視覚的に構成されており、情報の面から見るととても奥行きのあるUIを作ろうとしている.しかし影や、ハイライトに頼ろうとは思わない。   さて、それがデザインプロセスにどう影響するのか?   UIを持つシステムを作るうえでプロトタイプはとても重要だと言われますし、私もそう思います。問題はそのためにどんなツールを使うか。   例えばこんな製品が最近発売されたようです。   スマホアプリのペーパープロトタイピング用のノートを作成、販売開始いたしました。iPhone実寸のグリッド入り&各種バーのガイド線付ノートブックです。   確かにこの製品を使い紙の上でプロトタイプを作ることも可能でしょう。しかしiOS7から「動き」がUI設計の中で重要性を増しています。   異なる画面間の遷移を動的になめらかに遷移させるカスタムトランジション、画面部品に簡単に重力とかバネとか従来ゲームでよく用いられていた「物理エンジン」の動きを付加する機能、デバイスの動きを検知し、画面部品を動かすことができる機能等。そしてそれらによってDepthを感じさせようとしている。   紙の上で、こうした動きを含むデザインのプロトタイプが可能でしょうか?「動き」が付帯的な要素であれば「プロトだから」ということでそれらを省略することもできるでしょう。しかし「動き」がインタフェースデザインの中でより重要な意味を持つとしたら?   このようにiOS7がもたらした変化は従来「デザイナー」と「エンジニア」と呼ばれていた職種(個人的にはこのような固定的な職種の呼び方は問題があると思っていますが)の垣根についても再考を促すものです。   iOS7でどのような画面間遷移のアニメーションが可能になったかを知らずに画面設計ができるでしょうか?どのような動きが簡単に実装でき、どのような動きがそうでないのか知らずに仕様を決めることができるでしょうか?   極論を書きます。iOS7からは、デザイナーと呼ばれる人であっても、どのような動きが可能か、可能でないかを理解しなくては「良いデザイン」ができなくなるのではないか。そして実際に動くものの「手触り」を確かめずにどうして「良いデザイン」ができるか。   つまりiOS6以前よりもさらにデザイナーとエンジニアは緊密にインタラクションする必要がある、と主張したい。iOS7を作った側のトップ二人はこう述べています。   But the idea of how we could create this sense of depth, that was just the most phenomenal collaboration which required everything from motion graphics to sensing in the hardware to the most remarkable sort of algorithms from a software point of view.  引用元: Apple's Jonathan Ive and Craig Federighi: The Complete Interview   Depth-深みを感じさせるためには、モーショングラフィックスから、ハードウェアの姿勢のセンシングや素晴らしいアルゴリズムなどが互いに協力しあうことが必要だった。  つまりiOS7自体が、エンジニアリングとデザインと呼ばれているものの緊密な協力なしには成り立たないものだったのです。であれば、その上で動くアプリケーションが デザイナーが仕様を作る それを受けてエンジニアがコードを書く といった従来のやり方で作れるものでしょうか?   具体的にアプリのUIで説明しましょう。   最近Sunrise CalendarというiPhone用カレンダーアプリを使い始めました。iOS7の純正カレンダーアプリ(iPhone版)も先ほど述べたような「動き」をうまく使っていますが、これはさらに上を行っています。 例えばこの画面では下半分に個々の日の予定が表示され、上のほうに日付が並んでいます。     ここで日付が並んでいるエリアをスクロールすると、自動的にその部分の面積が大きくなり、個々の日の予定エリアが小さくなる。     ユーザがスクロールする、ということはその部分に着目しているということであり、それに応じて画面の「デザイン」を動的に変更しています。こうやって静止画だけ見ると「はあそうですか」と思うでしょう。しかし実際にiPhoneの上でさわってみると、その自然さ、ユーザを戸惑わせないコンテキスト切り替えの滑らかさに驚きます。このような「動き」を含んだデザインは静止画像だけで可能でしょうか?できないとすればどうすればよいのでしょう?   --------- 「へやくる!」の開発にあたっては開発の初期から「ワーキングプロトタイプ」を使うことを心がけました。iPad,iPhoneアプリのインタフェースがPC上のインタフェースと異なるのは「手触り」を評価する必要がある点。実機上で触って動かしてみないとそれが良いデザインか否かはわからない。   というわけで「手触り」「動き」を再現できるプロトをごりごり作る。捨てコードと割り切ってとにかく早く動くコードを作る。いわばダンボールと両面テープでモックアップを作っているようなものです。 もちろん製品のコードはそれとは別に作ります。開発の後半でもこのワーキングプロトタイプは新しいUIの検討をする際に「それなりに」役立ちました。捨てコードだから、せっかく作った部品がボツになっても泣かない(キッパリ)   とはいえ   ワーキングプロトタイプを作るのもそれなりに大変。というわけで「動き」を検討できるよいプロトタイプツールはないものですかねえ....  
アバター
はじめまして。池田と申します。   今回は、Xcode5のstoryboard上で、オブジェクトに対してAdd Missing Constraintsを適応した際の動作検証とその結果についてご紹介したいと思います。   AppleのAuto Layoutガイドを見ると、Add Missing Constraintsを適応することにより、「現在の配置の状態から必要な制約を推測し、自動的に追加する」と記述がありますが、ここでは、"推測"した結果どのような制約が追加されるのかを検証します。     Add Missing Constraintsの適応方法 storyboard上で、オブジェクトを選択し、Issues > Add Missing Constraintsを選択することで、そのオブジェクトに適応できます。   以下、独立したオブジェクトに適応するパターンと、周辺にオブジェクトがあるオブジェクトに適応するパターンでの検証結果をご紹介します。 また、検証結果は、Assistant EditorのPreview機能を用いて、 横画面の配置を確認しながら、紹介していきたいと思います。   独立したオブジェクトに適応した場合 左右位置が中央、上下位置が中央より少し上に配置されたボタンに対して適応します。 適応前 適応後   適応後は、superViewの左右中央に固定する制約と、上端からの位置を指定する制約が追加されています。横画面の配置を確認しても、左右中央、上端からの位置は縦画面の配置と変わらず、固定されていることが分かります。 今回の例では、左右中央としていますが、これを中央から少し左にずらすと、左端からの位置指定が制約として追加されます。 独立したオブジェクトに対してAdd Missing Constraintsを適応すると、左右位置の指定と、上下位置の指定が必要と推測され、どちらかの端に寄っていればその端からの位置指定、中央であれば中央固定の制約が追加される結果となりました。   周辺にオブジェクトがあるオブジェクトに適応した場合 次に、周辺にオブジェクトがあるオブジェクトに対する適応を検証してみたいと思います。 中央にボタンを配置し、その上下左右にボタンを配置した例で検証します。 適応前 適応後(中央のボタンに)   Add Missing Constraintsを適応したのは、中央のボタンになりますが、周辺のボタンの配置に対しても影響を及ぼしていることが分かります。 具体的な影響としては、中央のボタンから、周りのボタンへの間隔の制約と、整列の制約が追加されています。 横画面の配置を確認すると、中央にボタンが配置され、上下左右にボタンが配置されるという、縦画面の配置と同様の配置になっていることが分かります。   では次に、さらにオブジェクトを増やし、複雑なレイアウトにしてみようと思います。中央の上下左右にボタンを配置し、その更に上下左右にボタンを配置してみます。 適応前 適応後(中央のボタンに) 横向きの配置を確認すると、Add Missing Constraints適応後、中央のボタンと、その上下左右のボタンは縦画面の配置と同様の配置になっていますが、その外側のボタンは縦画面の配置とは異なった、意図しない配置になっています。 また、エラーが出ており、ここのエラーは、一番外側の4つのボタンの位置指定に対する制約が不足している旨のエラーが出ています。 そこで、制約が足りない4つのボタンに対して、それぞれAdd Missing Constraintsを適応します。 すると各ボタンに位置指定の制約が追加され、以下のようになります。 横画面の配置を確認すると、今度は、縦画面の配置と同様の配置となっており、エラーもなくなっていることが分かります。   まとめ 以上から、Add Missing Constraintsの適応は、 周りにオブジェクトがある場合、他のオブジェクトの配置にも影響を及ぼす 複雑なレイアウトの場合、完全に制約を追加しきれない場合もある などの注意点もありますが、一発、または複数回、この設定を適応していくことで、自動的にレイアウトを調整できる場合もあります。 この機能を最初見たときは、"推測"で制約が追加されるなんて、何が起こるか全然分からないし、なかなか使えないという思いが結構あったのですが、実際使ってみると、あ、うまく使えばレイアウトの設定、意外と省力化できるかもという感覚を持っています。 最終的には、オブジェクトのサイズの調整であったり、なんらかの調整は必要になってくるとは思いますが、まずざっくりとしたレイアウトを決める、画面サイズによらず、中央にあるレイアウトでオブジェクトを配置する、など、場合に応じて使ってみるのもよいかと思います。 設定しても、アンドゥですぐ戻せるので、一回試してみるのもありだと思います。   以上、今回の検証がレイアウト設定をされる際の参考になれば幸いです。
アバター
株式会社ネクストでエンジニアをやっております サム と申します。 突然ですが、iOSアプリケーションを開発したことがある人は必ず iOSシミュレータ でテストを行っていると思います。 しかし、そのテストは 動作確認だけ やっておりませんか? 実は、後少しだけ確認することで、 レンタリングの速度などを改善 することができます。 これにより、アニメーションなども比較的効率良く実行することができます。 今回は、意外に知っていそうで知らない「 iOSシミュレータのデバック 」について記事を書きます。 iOSシミュレータのメニューに「 デバッグ 」という項目があります。 こちらに次の4つの項目があると思います。 ブレンドレイヤー (Color Blended Layers) コピーイメージ (Color Copied Images) 不揃いのイメージ (Color Misaligned Images) オフスクリーンレンダリング (Color Off Screen Rendered) 今回は、よく使われる「ブレンドレイヤー」および「不揃いのイメージ」について説明します。 ・ブレンドレイヤー レイヤーが重なり合っている部分を色分けして表示してくれます。 複数のレイヤーが重なって描画されている部分は、赤の強調表示になります。 これを解消するには、対象となる部品の 背景色を透明ではなく、背景色と同一色に変更 することです。 赤い部分をなるべく削減 することで、描画性能が大幅に向上します。 ・不揃いのイメージ ソースピクセルがデスティネーションピクセルに揃っていない画像上に、黄色をオーバーレイして表示します。 次のソースコードを実行してみると - ( void )viewDidLoad { [ super viewDidLoad]; UIImage *homesKunImage = [UIImage imageNamed: @"homes_kun" ]; UIImageView *imageView = [[UIImageView alloc] initWithImage:homesKunImage]; // 画像を画面中央に表示する imageView.center = self .view.center; [ self .view addSubview:imageView]; } iOSシミュレータ上では正しく表示されているように見えます。 けれども、ここでiOSシミュレータにある「不揃いのイメージ」にチェックを入れると、次のように見えます。 このように、 見た目では正しく表示されているように見えても、実際には正しく表示されていない ことがよくあります。 この原因をデバッグログから探ってみます。 まず UIImageView の center を設定したときの前後でイメージビューの フレームの変化 を確認してみます。 NSLog( @"before: %@ " , NSStringFromCGRect(imageView.frame)); // 画像を画面中央に表示する imageView.center = self .view.center; NSLog( @"after: %@ " , NSStringFromCGRect(imageView.frame)); これを実行すると、次のようにログが出力されます。 before: {{0, 0}, {120.5, 141.5}} after: {{99.75, 213.25}, {120.5, 141.5}} 最初のフレームの座標は {0,0} の整数に対して、中央表示後は {99.75, 213.25} と浮動小数点になっています。 こちらが原因なのです。 では、この浮動小数点を丸めれば解決しそうですので CGRectIntegral を使った、次のソースコードを実行してみます。 NSLog( @"before: %@ " , NSStringFromCGRect(imageView.frame)); // 画像を画面中央に表示する imageView.center = self .view.center; // フレームの値をまとめる imageView.frame = CGRectIntegral(imageView.frame); NSLog( @"after: %@ " , NSStringFromCGRect(imageView.frame)); このような問題は、 画像サイズが奇数で作成されていることで発生 します。 こちらのデバッグログは before: {{0, 0}, {120.5, 141.5}} after: {{99, 213}, {122, 142}} 画像フレームサイズも丸められております。 そのため、 実際の画像サイズと表示されてる画像フレームが異なった ため、黄色にオーバーレイされているのです。 そこで、フレームサイズを元の画像に合わせてあげます。 NSLog( @"before: %@ " , NSStringFromCGRect(imageView.frame)); // 画像を画面中央に表示する imageView.center = self .view.center; // フレームの値をまとめる imageView.frame = CGRectIntegral(imageView.frame); // フレームサイズを調整する imageView.frame = CGRectMake(CGRectGetMinX(imageView.frame), CGRectGetMinY(imageView.frame), image.size.width, image.size.height); NSLog( @"after: %@ " , NSStringFromCGRect(imageView.frame)); いままであったオーバーレイはすべてなくなりました。 こちらのデバッグログは before: {{0, 0}, {120.5, 141.5}} after: {{99, 213}, {120.5, 141.5}} と、フレームの座標のみを設定したものになります。 このように、ほんの少し気を使うことで、アプリケーションはより快適に動作することでしょう。
アバター
大坪と申します。先日 TechCrunch Tokyo 2013 に参加しました。そこで聞いた内容のうち興味深かった点、そこから考えたことなどについてつらつらと。 一番おもしろかったのはWebサイト構築サービスWeeblyの創業者でCEOのDavid Rusenko氏の講演でした。 こちら に講演者の顔写真があります。 この写真の見たままの「とても若い」Rusenko氏。ばりっとスーツを着て立派なビジネスマン、、というよりはがんばってスーツを着ている高校生のようにも見えます。しかし話の内容はとても「高校生」などと言えるものではありませんでした。 学校(Penn State)を辞め、起業してサイトを作ったのはいいが、登録してくれる人はせいぜい二桁の前半。メディアにとりあげられたりすると一時的にユーザが増えるのだけど、そのあと元に戻ってしまう。ずっとそんな状態が続いた。ここらへんの話は自分でサイトを立ち上げたり、アプリをリリースしたことがある人ならば身につまされるはず。 一時期は銀行残高が$100をきった。そこで$650Kの資金調達に成功したけど、それを得るための書類の厚さはものすごかった。 スタートから18ヶ月たったが、ユーザは本格的には増えなかった。しかし20ヶ月で状況が好転しだした。ほっとしたのもつかのま、34ヶ月で貯金がつきかけた。何を払わなくちゃいけないか、何をのばせるかを必死に検討した。 48か月たってでコンスタントにユーザが増え始めた。今はユーザも増え、満足度も高い。(ここから現在成功している様子が語られますが、彼のスピーチの主眼はそこになかったように思います) そうした経験を語った後に、彼は3つ学んだことを挙げました。 #1 you can't succeed if you quit. 辞めたら成功できないよ 彼らは一年半も鳴かず飛ばずの状態が続き、ユーザが増え始めたのは4年後。それだけにこの言葉には重みがあります。もちろんいつまでも成功しないやり方を続ける人もいるわけですが、確かに辞めたらそこで終わり。 この講演では明確に述べませんでしたが、その間彼らはずっと次の項目にフォーカスしたのだと思います。 #2 Make something people want. 人々が欲しがるものを作れ ユーザに受け入れられることが一番重要。特許だの他のことはそれに比べれば細かなこと。 この言葉を「当然だ」と思う人はとてもラッキーな人か、働いた経験が浅い人だと思います。「人々が欲しがる物」ではなく「すぐ収益がでるもの」「自分たちが作りたいもの」「お客様に言われたもの」「上司が言ったもの」,,etcを作ることになります。 #3 Don' always listen to advice. アドバイスに従わなくてもいい この後講演したDisqus 創業者兼CEOのDaniel Ha氏は同じ内容をより詳しく述べていて advice = limited life experience + overgeneralization アドバイス=限られた経験+過度の一般化 いろいろな会社で働くと実感することですが「会社」とか「仕事」とか「常識」という言葉が意味するものは本当に様々です。ある会社では賞賛される行為が、別の会社では批難の対象となる。そしてどちらの会社もちゃんと法律を守りそれぞれ成功している。そうした状況を何度も経験します。 そうした経験を通じ、結局人間一人が経験できることというのはそれほど多くはないのではないか?と考えることになります。もしそうなら「他人に対するアドバイス」とは、その人の限られた経験だけを元に全く異なる文化の中で生きているかもしれない人の行動を評価することにほかなりません。 もちろん「普遍の真理」というのは存在し、それには耳を傾ける必要があります。しかし全てのアドバイスはそこまでの普遍性を持つものか? - Techcrunchから少し離れますが、Googleの元CEO Erick SchmitはGoogleに来た時このように振る舞ったと言われています。 エリック(・シュミット)は新しいゲームをプレーするために、 自分の振る舞いを完全に変えた。エリックほどの成功者であれば、 自分は万事心得ていると考えても許されるだろう。グーグルにやって来て、 おい青二才、俺がやり方を教えてやるよ、と彼が言ったって許されたはずだ。 そうではなく、彼は話を聞いた。そして観察した。 何が起きているのかを見極めた。 自分がこれまでうまくやってきたことのうち、 どの部分がグーグルをより良くするか、見極めたのだ。 (引用元: 文藝春秋|梅田望夫著「ウェブ時代 5つの定理」|ビジョナリーたちの名言リンク集 第5定理「大人の流儀」  ) おそらくErick Shumitはadviceについての先ほどの式を(明示的かどうかは別として)理解していたのだと想像します。自分の経験をそのままGoogleに持ち込もうとするのではなく、自分が経験した範囲でどのようなことがGoogleに活かせるのか慎重に考えたのだろう、と。 ここがGoogleのCEOと、酒の席でくだまいている「説教オヤジ」(あるいはそれに類する人達)の差異なのだろうと考えるわけです。 - もう一点印象深かったのはAirbnbのOle Ruch氏が言ったこの言葉。 100 people who love you is better than 1 million who kind of like you. 100万人に好かれるより、100人に愛されるべき 熱心なファンが100人いれば、その人達はサービスの良さを自ら伝えてくれる、と。この言葉をなんとなくは理解していても、その実現のために具体的な行動を起こしている会社はあまり多くないと思います。サービスが愛されるとはどういうことなのか。そのために何をして、どのようにその結果を計測するのか。それよりは「アクティブユーザ数」「セッション数」「クリック数」などのlike か loveかわからない数字だけを眺めている企業のほうが多いのではないでしょうか。 などと書いているとだんだん耳が痛くなっているのでこのへんで。 - 追伸:同じくTechCrunch Tokyo 2013に参加された方が書いた ひろゆき’s 意見: 「Strikingly」CEOが「TechCrunch Tokyo」で伝えたかった3つのこと にも共感を覚えます。StrikinglyのCEOが強調したことは以下の3点でした。 Don't quit Build half a product Create super fans - 追伸:本家の記事 「大事なのはメディアに載ることよりも諦めないで続けること」Weebly創業者が語る成功の3つの秘訣 | TechCrunch Japan が出ました。
アバター
大坪と申します。話題になっていた こちらの記事 に便乗して、私たちがどうして「 へやくる! 」をiOS7 onlyにしたのか。その結果はどうだったのかについて書きます。   へやくる!のコーディングが本格的にスタートしたのは、私がWWDC2013から帰って来た後の事でした。初めてお披露目されたiOS7には圧倒されました。ちまたでは   「とうとうiOSもフラットデザインか」     という言われ方をしていましたが、WWDCに参加していた人は誰一人そんな印象を 持たなかったと思います。それはまさにiOSのインタフェースはどうあるべきかを考え抜いた、深い洞察の具現化だと感じました。(スキューモーフィズムを好んでいたと言われるフォーストールが去ってから短期間でこれほどまでの変化を成し遂げた開発力には感服しますが、それはまた別の機会に)   iOS7がいつ正式リリースになるかの発表はもちろんありませんでしたが、毎年のサイクルからすると、どうも「へやくる!」のリリース時期と重なるような気がする。さてどうしよう?もちろん最新OS対応にしたいという気持ちはありましたが、すぐに全てのiPadユーザがiOS7に移行するわけではなかろう。まあ   「iOS6ベースで。ただしデザインはiOS7テイストを取り入れる」   ところかな、と思っておりました。   定例会議でそうした構想を話したところ、iOSサイドの開発を担当する人間から   「いや、ここはiOS7 onlyで最新のインタフェースを取り入れましょう!」   という言葉がありました。最新OS対応と言えば聞こえはいいですが、開発する側からすれば、サンプルもない、ドキュメントも限られる、NDA期間中はおおっぴらに情報交換もできない、といった茨の道を歩む事を意味します。 それを承知してなおiOS7 onlyを目指すとは。「へやくる!」自体挑戦的なUX実現を目標にしていましたので   「なんという心強い言葉。君がそういうなら、是非その方向で行こう!」   と言いました。先ほど述べた最新OS故の苦悩は全部iOSソフト開発者の肩にのしかかるわけですが、それを担う人間が挑戦しようというのだから「部外者」が止める理由は無い、などとのんきに考えておりました。   まさかそのクライアント開発が 自分に降ってくる とは夢にも思わず。     仔細は省きますが、クライアントの検索条件設定と物件一覧のところは自分で書くはめになったわけです。iOS7専用にしたんだから、新しい機能を取り入れよう、といくつかUI部品を試作しました。WWDCではプレゼンをする人が口々に「もうサンプルはサーバーにアップロードしてあるよ」と語っていた筈なのに、待てど暮らせどサンプルコードは利用可能にならない。結局WWDCのセッションビデオを何度も見直すはめになります。しかしそれをなんとか克服し、物理エンジンを取り入れたスライダーとか、UINavigationControllerのTransitionとか、あるいはメモ帳みたいなちょっとへこんで見える文字とか作りました。   しかし結論から言えば、これらは最終的な製品には反映されませんでした。理由は単純で、従来の部品と比較した時にUX上でのメリットが見いだせなかったからです。「へやくる!」はユーザに新しいUXを提供することを目標としており、iOS7の新機能のテスト台ではない。ですから土曜日をつぶして作った部品が月曜日にあっさり没になる、ということが何度も起こった訳ですが、そのこと自体誇るべきことだと思っています。(一エンジニアの立場では”しくしくしく”ですが)   リリースした後になってみると、iOS7対応ということで、App Storeの該当セクションに掲載していただいたり、あるいは「おすすめアプリ」として取り上げていただいたりしたことが、新規ユーザを増やすという点で大きな効果があったことは事実です。しかし一エンジニアとして考えた時にその最大のメリットは「簡素な美しさ」でした。   それは何のことか?   アプリを開発する人間はおそらく一番多くアプリ画面を眺めることになります。特にUI部分を担当するときはそうです。リリースが近づいてくるといろいろなことが起こり、疲労もたまり行き詰まったように感じることもあります。   変な言い方ですが、そういう時にiOS7とそれにマッチした簡素で美しい画面(これはiOS7のコンセプトを理解した上で画面をデザインしてくれた人の努力の成果です)と相対しているのと、かつての「ガラケーサイト」のようなデザインを観ているのとではモチベーションの湧き方が全然違う。少なくとも私にとってはそうです。自分たちは美しい、すばらしいものを作っているのだという思いは、よれよれになったエンジニアにとって「砂漠で死にかかっている男に対するコップ一杯の水」くらいの効果があるわけです。   iOS6までとiOS7ではデザインに対する考え方が大きく変わりました。もちろん両方の環境で動作するアプリを作る事はできる。しかし「デザイン」というのは表面的な意匠にとどまる物ではない。iOS7のデザインテーマとして挙げられているClarity, Deference,Depthというコンセプトについて深く考えれば、自ずと意匠だけではなくユーザとのインタラクション、画面設計自体が変わってくる事に気がつくでしょう。つまりiOS6とiOS7の共用アプリを作ろうとすればこうした事実についてかなり慎重に 考える必要がある、と主張したい。(具体例についてはまた別の機会に書くかもしれません)   WWDCでAppleが行ったiOS6/iOS7共用アプリについての説明は非常に歯切れが悪いものでした。一体何を言っているのだろう。考えたあげく、私は   「要するに作り直せ、といっているのだ」   と結論づけました。よれよれになりながらもようやくiOS7専用アプリをリリースした今では、そのことをより確信をもって語ることができます。   もちろんアプリ開発の事情は様々だと思います。あるバージョンのOSを使っている人が何%をきったらサポートから外す、というのは常に難しい判断です。しかし今回iOS7専用でアプリを開発するチャンスを得られた事は非常に幸運だったと今は考えています。
アバター