PlayFrameworkでキャッシュの有無によってViewを出し分けするサンプル
PlayFrameworkでキャッシュの有無によってViewを出し分けするサンプル
複数の画面間でフォームから入力した値を保持したかったのでキャッシュを使うことにしたのだけれど、
キャッシュの値の有無によって画面表示を変更しようとしたらつまづいたのでメモ。
サンプルプロジェクト
https://github.com/satomikko94/play-cache-sample
- PlayFramework 2.4
- Java 1.8
サンプルコード
PlayFrameworkでキャッシュの値の有無によってViewを出し分けするサンプル ref: h ...
実行結果
http://localhost:9000/ にアクセス。
初期画面
初期画面はCache has no data!と表示される。
フォームに適当な値を入力してSubmit
フォーム送信後
Submitすると、フォームの値が下に表示される。
キャッシュに入れているので、直後に画面を更新してもこの値は残ったまま。
キャッシュ期限の1分を過ぎるとまたCache has no data!と表示される。
ポイント
Cache.set
setCache.scala.htmlのフォームで入力した値をApplication.javaでTask型として取得し、
Cache.set("task", task, 60 * 1);
でキャッシュに保持している。キャッシュ期限は60 * 1 = 1分。
このキャッシュは他のクラスやViewから取り出すことが出来る。
キャッシュデータのviewでの取得
ここがつまづいた所。
この後のif文で使用するためには、キャッシュのデータを
@(task : Task = Cache.get("task").asInstanceOf[Task])
で取得してくる必要がある。asInstanceOf
でTask型に直すのを忘れずに。
この1行、これより前にHTMLが書かれていると
')' expected but '=' found.
というコンパイルエラーが表示されてしまうので
必ずincludeしてるhtmlの最初に持ってくる必要がある。
この件についてはちゃんとした理由書いてあるページあると思うのだけれど見つからなかった・・・
どなたかわかったら教えて下さい。
取得したキャッシュデータの利用
取得できればあとは簡単。if文は
@if(task == null) { }
このように@if
のなかで取得したデータを使用できる。
また、HTMLに取得したデータを埋め込みたい場合は
id : @task.id<br>
という使い方もできる。
Qiita
Apple WatchのNike Runningアプリ使ってみた。
Paris New Tech September 2014 に行ってきた
Paris New Tech September 2014 に行ってきた。
Paris New Tech September 2014 #PNT6 - Paris New Tech (Paris) - Meetup
6 new tech startup companies will present their products and technology (5 min demo+5 min Q&A).
スタートアップの企業が自社のサービスを簡単に紹介するイベント。
パリのイベントには珍しく英語での開催。ありがたい。
会社から徒歩10分くらいのCafeが会場だったんだけど、行ってみたら思った以上に普通のカフェBar。
ほんとにこんなとこで開催するのか?と思いつつ、とりあえずお酒頼んでみる。
上の階に行ってみたら、ちゃんと開催されてた。
紹介されていたのは、
自分の採寸の3Dアバター作ってネット上で服の試着が出来るサービスや
写真にブランドや場所のタグを付けてマネタイズにつなげるっていうサービス
Dropbox的なクラウドサービスやQiita Teamみたいな技術共有サービスなどなど、バラエティに富んでいた。
(Highly secure, European infrastructure っていうのが面白い。こっちの人的にはクラウドはヨーロッパのほうが安全みたいなイメージが有るのだろうか)
全部の発表が終わったら、「じゃ、あとは適当にやっといて」みたいなノリで主催者が撤収して懇親会タイム。ゆるい。
数人と話したけどみんな技術者じゃなくてマーケティングとか広告関連で来てるみたいだった。
あとカナダ育ちの香港人の女の人にあって、あたりまえだけどめちゃくちゃ英語がうまくて私も頑張らないとと実感。
その他イベント的に感じたこと
- 参加者は60-70人くらい
- Paris New Techだけど具体的な使ってる技術とか実装の話は全然ない。あくまでサービスの紹介
- BETA版リリースしてるから使ってねとか、人材募集してるよとか言ってたので、そういう目的の人が多かったのかもしれない
- 日本みたいにPC開いてる人はほぼいない。メモ取ってる人は少しだけいたけど、たいていみんな発表者の話ちゃんと聞いてる
- 発表5分・Q&A5分。質問する人はそこそこいる
- Wifiとかない。ケータイの電波すら危うい
- 飲み物は勝手にバーカウンターで頼んで持ってくスタイル
イベント一つでも日本と違う面が見れて面白いなー
Swiftで自分のクラス名を表示する方法
Swiftで自分のクラス名を表示する方法
NSOdjectのサブクラスのdiscriptionメソッドとかで自分のクラス名を表示したいと思ったのだけど、
Swiftではself.classが使えない。
discriptionメソッドで使うだけなので別にクラス名直書きでもいいのだけれど、
なんだかすっきりしないので調べてみた。
コンソール出力や、Unit testなどでクラスを比較するときに使える。
サンプルプロジェクト
https://github.com/satomikko94/PrintProjectName
実行結果
(コンソール出力)
Class name : PrintProjectName.PrintClassName or Class name : PrintProjectName.PrintClassName
解説
PrintClassName内のdescriptionメソッドで、
{Project Name}.{Class Name}
の形式でクラス名(及びプロジェクト名)を返している。
func description() -> String { return "Class name : \(NSStringFromClass(self.dynamicType)) or \nClass name : \(reflect(self).summary)" }
NSStringFromClass(self.dynamicType)
dynamicTypeを使うと、インスタンスのクラス自身(サブクラス化されていればサブクラス)が参照される。
(参考 : インスタンスメソッド内でクラスメソッドを呼ぶ #Swift)
Objective-Cのself.class
とだいたいおなじようにself.dynamicType
が使えると思われる。
ただ、self.dynamicType
はそのままコンソール出力すると(MetaType)
と出力されるだけなので、
NSStringFromClass
を利用してStringに変換すればOK!
reflect(self).summary
reflect()
メソッドはオブジェクトの情報を取得するメソッド。
そこに.summary
をつけることで、String形式に変換している。
これじゃだめだった
println("\(self.dynamicType)") // Prints "(Metatype)" println("\(object_getClassName(self))"); // Prints "0x7b680910 (Pointer)" println("\(self.className)") // Compile error! println(PrintClassName.self) // Prints "(Metatype)"
Qiitaにも投稿してみた
モンサンミッシェルに行って来た〜Capitaine Trainでチケット取って旅に出る方法
2週間ほど前だけど、パリからモンサンミッシェルに行ってきた。
その際Capitaine Trainというサービスを使って電車+バスのチケットを取ったのだけど、
これが結構便利で使いやすかったので、チケット予約や発券のやり方を書いておこうと思う。
モンサンミッシェル以外の都市に行くときも使えると思う。
Capitaine Train
Capitaine Train: train tickets 6
カテゴリ: 交通
Google Playで詳細を見る
Webサイトの他に、iPhone, Android Appがある(実際私はAndroid Appで予約した)
今回はWebサイトの画面で。
(1) Sine up
会員登録はFacebook認証使って出来る。便利。FBアカウントない人はここで会員登録
(2) 出発元、行き先、往復の時間を指定。
- 時間は前後の時間を出してくれるのでだいたいでOK
- 同行者がいる場合はここで指定する。身分を確認されることがあるから名前はちゃんと入れたほうがいいらしい(今回は全くチケット確認されなかったけど。。)
(3) 行きの道を指定
- 電車+バス全て含めた時間と料金が表示される→電車会社のHPで予約するより楽!
- 1st, 2ndは好きな方を選ぶ(2ndでも十分快適だった)
- 右下のSeatingのところで座席タイプの希望を出せる(次で詳しく説明)
- Indifferent : なんでもOK
- Window : 窓側
- Aisle : 通路側
- Twin side-by-side : 隣同士。2人とかで行くとき用
- Next to... : 多分どこか特定の席と隣にしたいときに使う。詳細不明
- その下のFacing direction of travelのチェックを入れると進行方向の向きの席を希望できる。(わたしはこれやり忘れて逆向きだった。。。)
最後にSELECT(price)のボタンを押すと、次に進む
(4) 帰りの道を指定。
これは行きと一緒
(5) 金額、時間、名前を確認。
OKだったらPAY(price)のボタンを押すと、クレジットカード入力画面に行ける。
ちなみにここまで行けば1回Cartに予約情報が入ってる状態になるので、1回閉じてもCartのところを見れば自分が選択したチケットが表示される。
なのでカード情報の入力はあとからでもOK。
また、下に黄色で囲まれて書いてある「can only be...」は、チケットが駅じゃないと発券できないという意味。
チケットの発券方法
上で言った通りチケットは駅の"SNCF self machine"で発券する必要がある。
発券は当日モンパルナスとか出発する駅で行ってもいいし、前日以前にあらかじめ他の駅で発券することも可能。
何がいいかというと、駅でのチケット発券にはクレジットカードが必要ない。たまに機械で日本のクレジットカードが読み取られなかった、みたいな話も聞くので、これはかなり楽で安心。
駅にあるこういう黄色い機械で発券できる。
発券の仕方は以下のリンクに詳しく載っているのだけど、ここでくわしく説明する。
How do I print my ticket at a French station? - Capitaine Train Help (FAQ)
(1)メールを確認
Capitaine Trainでチケットを予約するとメールが送られてくる。
そのメール本文に書いてある以下の情報を確認。
Reference:
• {6文字の英数字} / {自分の名字}
メールには添付ファイルもあるけど、実際チケット発券に必要なのはこの部分だけ。
(2)真ん中の‘Collection with a file reference number’を選択
(画像引用元上記サイト)
真ん中の一番下にある緑で選択されてるボタンがそれ。上2つはクレジットカード使うやつで違うので注意
(3)‘File and electronic ticket collection’を選択
右側に並んでるボタンから選択。
(4)メールにあった英数字を入力
入力画面が出てくるので、前述したメールにあった{6文字の英数字}を入力
(5)苗字を入力
さらに入力画面が出てくるので、前述したメールにあった{自分の名字}を入力
(6)チケットを選択して印刷
チケットの確認画面が出てくるので、印刷するチケットを選択してPrintボタンを押す。
同行者がいたりで何枚か発見が必要な場合でも、1回で発券できる
(7)チケットを確認
印刷されてくるチケットがこれ。
画像が見にくいけど、上のチケットの真ん中の方に書いてある「TGV 8091」が電車番号。
何番線のホームかはチケットに書かれてないので、当日自分の番号の電車が何番線に来るのか駅の電光掲示板などで確認すること。
また、右側に書かれている「VOITURE 17」は17号車、「PLACE ASSISE 77」は77番の席という意味。何号車かは電車に書いてある。
あと行き先や乗り継ぎ、時間も要確認!
(わたしはてっきり行きも帰りもレンヌで乗り継ぎかと思ってたら、行きはドル=ド=ブルターニュ乗り換えだって電車乗る直前に気づいた。危なかった・・・)
以上がチケット予約して発券するまで。
Capitaine Trainは電車とバスいっぺんに予約できるし候補の時間を色々出してくれるところと、チケット発券がクレカ無しで出来るのがすごく良かったと思う。
モンサンミッシェルまでの金額・時間について
最後にチケットの取り方関係ないけど、モンサンミッシェルまでの金額・時間について。
自分でチケット取っていく方法と、パリからバスツアーで行く方法を比べてみる。
日帰りで行って帰ってくるのを前提。どっちもそんな詳しい知識ないのでだいたい。。
行き方 | 値段 | モンサンミッシェルで過ごせる時間 |
---|---|---|
電車+バス | 交通費:往復で75€(10月)〜140€(8月) 修道院チケット:9€ (日本語オーディオガイド+4.5€) お昼代:約15-20€ -------------------------------- 計:約110〜175€ |
4-5時間 |
バスツアー | 交通費・チケット代・ガイド代・お昼代 (場合によっては他の場所の観光代)込み ------------------------------ 計:約130〜180€ |
2-4時間 |
私の場合は8月3連休の中日という絶好のタイミングで行ったので交通費だけで140€したけれど、日本語ガイドとかいらないから自分でゆっくり回りたくて電車で行った。
値段も大きく変わらないので(場合によってはツアーのほうが安い)、どっちがおすすめかは人それぞれだと思う。
今くらいの時期なら電車で行ったほうが安い。
あと何点かあるとしたら
- 4,5時間あってもお昼食べてチケット並んで修道院と島探索しておみやげ買って、ってしてたらほんとにあっという間だった。島滞在2時間とかのバスツアーはほんとに行ってちょっと見て終わりになると思う。
- 団体で行けば団体専用入り口で並ばずに修道院に入れるので、そこはツアーで行ったほうが時間短縮になる。8月に行ったら20,30分くらいは並んだ
- Capitaine Trainでみた時に片道4.5-5時間を超えるような道のりだったら、やめてバスツアーにした方がいい(or日にち変えて再度検索)。私の場合は電車バス含めて片道4時間弱で行けた。
そんな感じで!いつかは泊まりで行きたいなあ。
皆様よい旅を!Bon Voyage!
SwiftでUILabelにHTMLを表示する方法
SwiftでUILabelにHTMLを表示する方法
Objective-Cとあまり変わらないけど、若干つまづいたのでメモ。
注)UILabelなので、あくまで表示しかできません。<a>タグでリンククリックとかさせたい場合はUIWebView使いましょう
サンプルプロジェクト
https://github.com/satomikko94/HTMLToLabel
サンプルコード
var htmlText = "空は<font color=\"blue\">青い</font>。<br>" + "An apple is <font color=\"red\">red</font>." var err:NSError? self.htmlLabel.attributedText = NSAttributedString( data: htmlText.dataUsingEncoding(NSUnicodeStringEncoding, allowLossyConversion: true), options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType], documentAttributes: nil, error: &err) self.htmlLabel.font = UIFont(name: "System", size: 14)
実行結果
ポイント
NSAttributedString
基本的には以下のリンク(Obj-C)のとおり、NSAttributedStringを使ってHTMLを変換しています
xcode - Display HTML text in UILabel iphone - Stack Overflow
NSErrorはOptionalに
NSErrorの値は必ずnilが入りうるので、?をつけてoptional型にしましょう。
これを忘れると "Extra argument 'data' in call" とか全然関係なさそうなコンパイルエラーになります
fontの設定
HTMLを表示すると、Storyboardで設定したSystemフォントが英字で無効になっちゃうので あとからUIFontで設定してます。
SwiftではfontWithNameが非推奨になってinitでfont設定するようになったようですね
UILabelのLinesは0に
HTMLに限ったことではないですが、UILabelの値が可変で2行以上表示させたい場合には
StoryBoardでUILabelのLinesを0に設定しておきましょう
P.S.
同じ内容だけど初めてQiitaに投稿してみた。
Swiftのクラスメソッドの中でクラス定数を使う
私もちゃんと理解してないんだけど、メモ用。Swift限定の仕様じゃないかもしれない。
変なとこあったらご指摘ください。
Swiftのクラスメソッド(SwiftではType Methodかな)の中でクラス定数を使おうとした。
#define TEST_VALUE 1 @implementation TestClass
みたいになってるクラスを書き換えたかったのでやってみると、コンパイルエラーで止められる。。。
class ClassHasInstanceMethod { let testValue:Int = 1 class let testValue2:Int = 1 // Error! Class variables not yet supported func getValue() -> Int{ return testValue } class func getValue2() -> Int{ return testValue // Error! 'ClassHasInstanceMethod.Type' does not have a member named 'testValue' } } var instance = ClassHasInstanceMethod() println(instance.getValue()) // 1
not yet supportedってなんなんだって話なのですが、とりあえず使えない。
あとちゃんと定義してるのにdoes not have a member
って言われてさらに腑に落ちない。
(ちなみにjavaっぽくstaticもつけてみたけど、static letはだめっぽい)
結局いろいろ試行錯誤したら、下のようにするとどうにか動いた。
private let testValue:Int = 1 // Define constant out of class class ClassHasTypeMethod { class func getValue() -> Int{ return testValue } } println(ClassHasTypeMethod.getValue()) // 1
class宣言の外で定数を定義すると、そのファイル内で使える定数になるみたい
(他のクラスから使わないようにするならprivateをつける。)
そういわれてみればObj-Cの#defineも@implementationの前でやってるし、これが普通なのか・・・?