Think Big Act Local
iPhone開発を軸にブレブレの記事を書いていきます。
2023-04-14T10:25:42+09:00
himaratsu
Hatena::Blog
hatenablog://blog/11696248318752807205
iOSDC 2016に参加してきたよ #iosdc
hatenablog://entry/10328749687180399750
2016-08-23T02:16:21+09:00
2022-02-24T19:50:48+09:00 iOSDC 2016という、日本最大級のiOSのカンファレンスに参加してきました。 iosdc.jp iOSDCはiOS・その周辺技術に関するカンファレンスで、公式サイトには「iOSエンジニアが聞いて面白ければ何でもOK」と説明されています。 トークは数多くの応募の中から運営スタッフにより採択されます。当日は技術的なテーマはもちろん、「海外のカンファレンスで登壇する」や「ハッピーな開発チームを築く」など、幅広い内容のトークが行われました。 以下、参加した記録として気になったセッションや会場の様子などを振り返ってみたいと思います。 振り返り 会場 会場は練馬のCoconeriホールという場所でし…
<p>iOSDC 2016という、日本最大級の<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>のカンファレンスに参加してきました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fiosdc.jp%2F2016%2F" title="iOS Developers Conference Japan 2016" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://iosdc.jp/2016/">iosdc.jp</a></cite></p>
<p>iOSDCは<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>・その周辺技術に関するカンファレンスで、公式サイトには<b>「<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>エンジニアが聞いて面白ければ何でもOK」</b>と説明されています。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>は数多くの応募の中から運営スタッフにより採択されます。当日は技術的なテーマはもちろん、「海外のカンファレンスで登壇する」や「ハッピーな開発チームを築く」など、幅広い内容の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>が行われました。</p>
<p>以下、参加した記録として気になったセッションや会場の様子などを振り返ってみたいと思います。</p>
<h1>振り返り</h1>
<h2>会場</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160823/20160823010812.jpg" alt="f:id:himaratsu:20160823010812j:plain" width="768" height="1024" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>会場は練馬のCoconeriホールという場所でした。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fwww.nerima-idc.or.jp%2Fplaza%2Fcoconeri%2Findex.html.html" title="練馬区立 区民・産業プラザ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://www.nerima-idc.or.jp/plaza/coconeri/index.html.html">www.nerima-idc.or.jp</a></cite></p>
<p>個人的にちゃんと練馬に上陸するのは始めてで、最初は「渋谷近辺じゃないのか」と思ってたんですが、行ってみると案外練馬近いし、家から交通の便も良いし、子連れのお母さん方とかが歩いてたりといつもと異なる環境で、良いコンディションでイベントを楽しめました。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160823/20160823013359.jpg" alt="f:id:himaratsu:20160823013359j:plain" width="1024" height="768" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>が行われる部屋はこんな感じで、かなり広い空間でした。(A/Bトラックの2部屋に分かれていて、写真は大きい部屋の方のAトラック)<br />
朝から座席がギッチリ埋まっていて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>エンジニアたちの早起きスキルに驚かされました。</p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a></h2>
<p>聞いた、もしくは動画でみた<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>のうち、印象深いものを並べてみます。</p>
<h4>海外の<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>カンファレンスに登壇する - 完全版</h4>
<script async class="speakerdeck-embed" data-id="e997b3faecc749d197b31c7ef93aa3c4" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
<p><a href="http://blog.hatena.ne.jp/shu223/">id:shu223</a> さんによる、英語が苦手だったスタート地点からいかに海外カンファレンスで登壇するに至ったか、そのモチベーションと攻略法などのお話。<br />
海外で登壇するという面白さはもちろんのこと、目標を先に設定して、そこから逆算で今自分がやるべきことを決めてやっていく堤さんの生き方がすごいなと思いました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fshu223.hatenablog.com%2Fentry%2F20160822%2F1471822768" title="iOSDCで発表しました『海外のiOSカンファレンスに登壇する - 完全版』 #iOSDC - その後のその後" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://d.hatena.ne.jp/shu223/20160822/1471822768">d.hatena.ne.jp</a></cite></p>
<h4>RxSwiftは開発をどう変えたか?</h4>
<p><a href="http://blog.ishkawa.org/talks/2016-08-20-iosdc/">http://blog.ishkawa.org/talks/2016-08-20-iosdc/</a><cite class="hatena-citation"><a href="http://blog.ishkawa.org/talks/2016-08-20-iosdc/">blog.ishkawa.org</a></cite></p>
<p><a href="https://twitter.com/_ishkawa">@_ishkawa</a>さんによる、RxSwiftを使った実装の紹介と、導入により開発がどのように変わるのか、というお話。<br />
Rx は以前から興味がありつつも機会を作れずまだ試せてないのですが、その心にまた火がつけられました。記法を覚えるまでには少し時間がかかりそうですが、処理の流れが追いやすくなるので見通しの良いコードが書けるし、コードレビューも行いやすくなりそうだなと感じました。</p>
<h4>SwiftでのGeoFence実装 - Tipsを添えて</h4>
<script async class="speakerdeck-embed" data-id="be458fb033f64558ad81752177c4f3d9" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
<p><a href="https://twitter.com/shmdevelop">@shmdevelop</a>さんによる、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>のGeoFence(正確にはGeographical Region Monitoring)のまとめとTipsの紹介。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>の位置情報プログラミングは色々なパターンがあり、その複雑さは年々難しくなっていってます。自分も最近実装したのですが、ドキュメント通りに実装しても挙動が怪しかったり、テストをしても不安な部分があったのですが、この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>を聞いてどこが実装による不具合でどこがOS挙動の怪しさなのかが分かってとても助かりました。</p>
<h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> で快適な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>ライフを追い求める</h4>
<script async class="speakerdeck-embed" data-id="9d35c8e973864907a2070adda4f8d6d0" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>
<p><a href="https://twitter.com/dealforest">@dealforest</a>さんによる<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>の話。<br />
プログラミングの大半は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>で、その<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>の効率をあげるためにどんなことをしてるか?のハウツーが複数紹介されました。出てくるケースがどれも「あ、これ困って諦めてたわ。。」というようなもので、各ケースでどう<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>情報を集めるかという話は毎回うならされました。今回のiOSDCで最も明日から役に立つ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>だったと思います。ベスト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>賞の第3位を受賞されてました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdealforest.hatenablog.com%2Fentry%2F2016%2F08%2F22%2F163156" title="iOSDC でベストトーク賞(3位)をいただきました - NANAIRO" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://dealforest.hatenablog.com/entry/2016/08/22/163156">dealforest.hatenablog.com</a></cite></p>
<h2>ランチ</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160823/20160823013330.jpg" alt="f:id:himaratsu:20160823013330j:plain" width="768" height="1024" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>せっかく初練馬だったので、ランチは地元住まいの先輩おすすめのラーメン屋にいきました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Ftabelog.com%2Ftokyo%2FA1321%2FA132102%2F13153294%2F" title="RAMEN GOTTSU (練馬/ラーメン)" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://tabelog.com/tokyo/A1321/A132102/13153294/">tabelog.com</a></cite></p>
<p>お店も綺麗だしとても美味しかったです。スープは濃厚な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C6%DA%B9%FC%B5%FB%B2%F0">豚骨魚介</a>でした。</p>
<h2>Tシャツ</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160823/20160823013725.jpg" alt="f:id:himaratsu:20160823013725j:plain" width="1024" height="768" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>当日、参加者にはTシャツが配られたのですが、役割や参加チケットの種類によって色が分けられていました。スタッフはピンク、登壇者は緑、スポンサーはオレンジなど。
パッと見でどういう方か分かるので、とてもコミュニケーションをとりやすかったです!</p>
<h2>宣伝</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160823/20160823014258.jpg" alt="f:id:himaratsu:20160823014258j:plain" width="768" height="1024" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>自分はスポンサーチケットで参加させていただきました。無限コーヒーエリアの近くのジョブボードにポスターを貼っていたのですが気づいた方はおられたでしょうか?</p>
<p>ヤフーでは一緒に世の中の課題を解決していける仲間を募集しています。少しでも興味がある方は↓のページを見てみてね!</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fhr.yahoo.co.jp%2F" title="採用情報 - ヤフー株式会社" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://hr.yahoo.co.jp/">hr.yahoo.co.jp</a></cite></p>
<h1>まとめ</h1>
<p>iOSDC 2016、最高に楽しかったです!<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>に興味のあるエンジニアやデザイナーがこの規模で集うのはすごいですね。<br />
今回は普通に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>を聞くだけの人として参加したのですが、こういうカンファレンスは登壇者 or スタッフになった方が数倍楽しそうだなと感じたので、来年も開催されるようであればそんな形で参加したいと思います。</p>
<p>運営スタッフのみなさま、登壇者のみなさま、参加者のみなさま、ありがとうございました。おつかれさまでした!!</p>
himaratsu
potatotipsでUICollectionViewの並び替えのAPIについて発表してきたよ
hatenablog://entry/10328749687175288730
2016-08-17T23:38:40+09:00
2022-02-24T19:50:52+09:00 FiNCさんで開催された、potatotips #31 で発表してきました。 potatotips.connpass.com 発表した内容 タイトルの通り、UICollectionViewのCellをインタラクティブに並び替えるAPIの紹介です。 デモ こんな感じで、 CollectionViewの(インタラクティブな)並び替え サイズの異なるCell間の並び替え pagingEnabled=trueの場合の並び替え などができます。iPhoneのホーム画面のような挙動ですね。 経緯 WWDC2016で参加したセッションの1つに「What's New in UICollectionView i…
<p>FiNCさんで開催された、potatotips #31 で発表してきました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fpotatotips.connpass.com%2Fevent%2F34614%2F" title="potatotips #31 (iOS/Android開発Tips共有会) (2016/07/21 19:00〜)" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://potatotips.connpass.com/event/34614/">potatotips.connpass.com</a></cite></p>
<h1>発表した内容</h1>
<script async class="speakerdeck-embed" data-id="1b344e142b264929b4cdec6abf43528e" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
<p>タイトルの通り、UICollectionViewのCellを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A5%E9%A5%AF%A5%C6%A5%A3%A5%D6">インタラクティブ</a>に並び替える<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の紹介です。</p>
<h2>デモ</h2>
<p><img src="https://github.com/himaratsu/CollectionViewInteractiveSortSample/blob/master/demo.gif?raw=true" alt="" /></p>
<p>こんな感じで、</p>
<ul>
<li>CollectionViewの(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A5%E9%A5%AF%A5%C6%A5%A3%A5%D6">インタラクティブ</a>な)並び替え</li>
<li>サイズの異なるCell間の並び替え</li>
<li><code>pagingEnabled=true</code>の場合の並び替え</li>
</ul>
<p>などができます。<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>のホーム画面のような挙動ですね。</p>
<h2>経緯</h2>
<p>WWDC2016で参加したセッションの1つに<a href="https://developer.apple.com/videos/play/wwdc2016/219/">「What's New in UICollectionView in iOS 10」</a>というのがありました。<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS%2010">iOS 10</a>でUICollectionViewがどう変わったか、どのような新しい<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>が追加されたかを紹介するセッションなのですが、そこでUICollectionViewにも並び替えのための<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>があることを知りました。</p>
<p>おー、これは!っと思って盛り上がったのですが、オチとして、このAPIsは<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS%209">iOS 9</a>からすでに提供されていたことに調べていくうちに気づきましたw<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS%2010">iOS 10</a>からスクロールがスムーズになったことで、並び替えの体験もより良くなったぜ!という紹介だったようです。</p>
<p>そんなわけで新しい<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>ではなかったのですが、自分は知らなかったし、そんなにネット上に情報が出てないような気もしたので、potatotipsのLTで紹介してきました。</p>
<h2>簡単な説明</h2>
<p>並び替えにはUICollectionView, UICollectionViewDataSourceの以下の<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を使います。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synComment">// UICollectionView</span>
<span class="synType">@available</span><span class="synSpecial">(</span><span class="synType">iOS 9.0</span>,<span class="synType"> *</span><span class="synSpecial">)</span>
<span class="synPreProc">func</span> <span class="synIdentifier">beginInteractiveMovementForItem</span>(at indexPath<span class="synSpecial">:</span> <span class="synType">IndexPath</span>) <span class="synSpecial">-></span> <span class="synType">Bool</span>
<span class="synType">@available</span><span class="synSpecial">(</span><span class="synType">iOS 9.0</span>,<span class="synType"> *</span><span class="synSpecial">)</span>
<span class="synPreProc">func</span> <span class="synIdentifier">updateInteractiveMovementTargetPosition</span>(_ targetPosition<span class="synSpecial">:</span> <span class="synType">CGPoint</span>)
<span class="synType">@available</span><span class="synSpecial">(</span><span class="synType">iOS 9.0</span>,<span class="synType"> *</span><span class="synSpecial">)</span>
<span class="synPreProc">func</span> <span class="synIdentifier">endInteractiveMovement</span>()
<span class="synType">@available</span><span class="synSpecial">(</span><span class="synType">iOS 9.0</span>,<span class="synType"> *</span><span class="synSpecial">)</span>
<span class="synPreProc">func</span> <span class="synIdentifier">cancelInteractiveMovement</span>()
<span class="synComment">// UICollectionViewDataSource</span>
<span class="synType">@objc</span><span class="synSpecial">(</span><span class="synType">collectionView:canMoveItemAtIndexPath:</span><span class="synSpecial">)</span> <span class="synPreProc">func</span> <span class="synIdentifier">collectionView</span>(_ collectionView<span class="synSpecial">:</span> <span class="synType">UICollectionView</span>, canMoveItemAt indexPath<span class="synSpecial">:</span> <span class="synType">IndexPath</span>) <span class="synSpecial">-></span> <span class="synType">Bool</span>
<span class="synPreProc">func</span> <span class="synIdentifier">collectionView</span>(_ collectionView<span class="synSpecial">:</span> <span class="synType">UICollectionView</span>, moveItemAt sourceIndexPath<span class="synSpecial">:</span> <span class="synType">IndexPath</span>, to destinationIndexPath<span class="synSpecial">:</span> <span class="synType">IndexPath</span>)
</pre>
<p>UILongPressGestureなどを使って、並び替えの開始のタイミング、移動のタイミング、終了のタイミングで上記の<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を呼ぶことで実装できます。<br />
UITableViewと同じく、並び替えが終わったときにデータを入れ替えする処理を実装する必要があるのですが、ここでデータの不整合が起こるとクラッシュしてしまうので注意が必要です。</p>
<h2>サンプルコード</h2>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fhimaratsu%2FCollectionViewInteractiveSortSample" title="GitHub - himaratsu/CollectionViewInteractiveSortSample" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/himaratsu/CollectionViewInteractiveSortSample">github.com</a></cite></p>
<h1>まとめ</h1>
<p>久しぶりにpotatotipsで発表するなー、と思って数えてみたらなんと2年ぶりの発表でした。
しばらくぶりのみなさまとお話しできてとても楽しかったです。</p>
<p>参加者のみなさま、素敵なオフィスにお邪魔させていただいたFiNCのみなさま、ありがとうございました!</p>
<h1>関連してそうな記事</h1>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fpotatotips26" title="第26回はSupershipで開催! #potatotips で発表されたiOSのtipsまとめ - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/potatotips26">himaratsu.hatenablog.com</a></cite></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Ftableview%2Feditmode" title="UITableView の編集モードを利用してデータの削除や並び替えを行う - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/tableview/editmode">himaratsu.hatenablog.com</a></cite></p>
<p><a href="http://himaratsu.hatenablog.com/entry/meyasubaco">http://himaratsu.hatenablog.com/entry/meyasubaco</a><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/meyasubaco">himaratsu.hatenablog.com</a></cite></p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160817/20160817234145.png" alt="f:id:himaratsu:20160817234145p:plain" width="401" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
himaratsu
【書評】基本が身につくAndroidアプリ開発入門書
hatenablog://entry/10328749687177323660
2016-08-09T20:22:26+09:00
2022-02-24T20:50:49+09:00 著者の森さんより、『基本からしっかり身につく Androidアプリ開発入門』を献本いただきました。 タイトルの通りAndroidアプリ開発をこれからはじめたい人向けの本で、Amazonでもベストセラーになっているようです。 この本は「ヤフー黒帯シリーズ」として出版されています。黒帯とはヤフーの中で特に優秀な人材に付与される称号で、著者の森さんはAndroid技術黒帯に認定されています。 iOSアプリ入門の黒帯本が少し前に出ていて、自分も読んだのですが、今回のAndroid黒帯本も構成などはそれに似ていると思います。 本気ではじめるiPhoneアプリ作り Xcode 7.x+Swift 2.x対…
<p>著者の森さんより、『基本<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%AB%A4%E9%A4%B7">からし</a>っかり身につく <a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>入門』を献本いただきました。</p>
<p><a href="https://www.instagram.com/p/BIg2PiShLkO/"><img src="https://www.instagram.com/p/BIg2PiShLkO/media/?size=l" alt="" /></a></p>
<p>タイトルの通り<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>をこれからはじめたい人向けの本で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Amazon">Amazon</a>でもベストセラーになっているようです。</p>
<p>この本は「ヤフー黒帯シリーズ」として出版されています。<a href="http://ir.yahoo.co.jp/jp/archives/irreport/2012q4/report/index.html">黒帯とはヤフーの中で特に優秀な人材に付与される称号</a>で、著者の森さんは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>技術黒帯に認定されています。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>アプリ入門の黒帯本が少し前に出ていて、自分も読んだのですが、今回の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>黒帯本も構成などはそれに似ていると思います。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B01C804DNO?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51Oh5VqTuZL._SL500_.jpg" class="hatena-asin-detail-image" alt="本気ではじめるiPhoneアプリ作り Xcode 7.x+Swift 2.x対応 黒帯エンジニアがしっかり教える基本テクニック (ヤフー黒帯シリーズ)" title="本気ではじめるiPhoneアプリ作り Xcode 7.x+Swift 2.x対応 黒帯エンジニアがしっかり教える基本テクニック (ヤフー黒帯シリーズ)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B01C804DNO?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">本気ではじめるiPhoneアプリ作り Xcode 7.x+Swift 2.x対応 黒帯エンジニアがしっかり教える基本テクニック (ヤフー黒帯シリーズ)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C0%BE%20%CB%E1%B2%A7" class="keyword">西 磨翁</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/SB%A5%AF%A5%EA%A5%A8%A5%A4%A5%C6%A5%A3%A5%D6">SBクリエイティブ</a></li></ul><a href="https://www.amazon.co.jp/dp/B01C804DNO?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<h1>目次</h1>
<p>本の目次は以下のようになっています。</p>
<ul>
<li>第1章 <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>の準備</li>
<li>第2章 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>アプリを構成する要素</li>
<li>第3章 はじめてのアプリ</li>
<li>第4章 データの保存と共有</li>
<li>第5章 通信とバックグラウンド処理</li>
<li>第6章 カメラの撮影</li>
<li>第7章 ユーザーの位置と地図</li>
<li>第8章 アプリの公開</li>
</ul>
<p>第1章では<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>に着手する前に考えるべきことが簡潔にまとめられています。
第2章では<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>で登場する「アクティビティ」「サービス」などの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>の説明。
第3~7章ではサンプルアプリを実際に作りながら<a class="keyword" href="http://d.hatena.ne.jp/keyword/xml">xml</a>によるレイアウトや<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>のクラスを使った様々な実装を学んでいくことができます。
最後の第8章で、自分の開発したアプリを<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Play">Google Play</a>に公開するまでの手順が紹介されています。</p>
<p>実はこれまでにも独学で、Webのドキュメントを読みながら<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>開発に挑戦したことがあったのですが、<strong>「フラグメント」「サービス」「ブロードキャストレシーバ」</strong>などの<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>にはない考え方がいまいち理解できず、挫折してしまいました。
この本では丁寧な説明だけでなく、実際にその<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>を使ったサンプルアプリを作る過程があるので、しっかりと理解することができます。</p>
<p>また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>との大きな違いに<a class="keyword" href="http://d.hatena.ne.jp/keyword/xml">xml</a>によるレイアウトがあると思いますが、こちらも実際に手を動かしながら学べます。ある程度分かってくると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS%209">iOS 9</a>からのStackViewと同じような考え方だなとか、自分の知っている知識に置き換えて理解できるので腹落ちしますね。</p>
<p>新しい言語を学ぶ場合、ある地点からはWeb上のドキュメントや<a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a>のコードなどを読んで勉強できるんですが、そこにいくまでが大変です。
この本は最初の一歩目に最適な本だと感じました。</p>
<h1>環境構築からサポート</h1>
<p>本書は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android%20Studio">Android Studio</a> 2.xに対応しています。少しでもバージョンが違うと<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>が違ったりして本質的でない部分でハマったりするので、最新の環境に対応してくれてるのは嬉しいですね。</p>
<p>また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>開発入門は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a>を落としてハイスタートの<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>とは違って、<a class="keyword" href="http://d.hatena.ne.jp/keyword/JDK">JDK</a>を落として、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%DF%A5%E5%A5%EC%A1%BC%A5%BF">エミュレータ</a>を設定して、必要であればgradleファイルをほげほげして…みたいな、前準備が大変なイメージでした。
<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android%20Studio">Android Studio</a>が賢くなったのもあると思いますが、本にしたがえばスンナリ環境構築出来てしまうので、最初の障壁が超えられるのも助かります。</p>
<p>章の間にコラムがあるのですが、gradle ファイルがどういう役割かとか、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android%20Studio">Android Studio</a> が登場して以前と比べてどう環境が変わったかなどにも触れられていて、歴史を知れたのも面白かったです。</p>
<h1>画像が多く親切な説明</h1>
<p>本書では説明の随所に画像が差し込まれていて、迷うことなく進めることができます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160803/20160803130156.jpg" alt="f:id:himaratsu:20160803130156j:plain" width="768" height="1024" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>例えば上の画像は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android%20Studio">Android Studio</a>の機能で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/xml">xml</a>で組んだレイアウトをプレビューしてくれるものですが、こういう感じでどんな機能が<a class="keyword" href="http://d.hatena.ne.jp/keyword/IDE">IDE</a>にあるのか教えてくれます。</p>
<p>自分が4年くらい使っている<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a>でもまだ知らない便利機能があったりしますし、こういう便利機能は先に体系的に学ぶのが良いと思います。</p>
<p>まだ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/IDE">IDE</a>を使っての開発は、純粋な<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>に加えて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android%20Studio">Android Studio</a>自体の学習も必要です。</p>
<p>様々な機能があるなかで、どの機能をよく使うのか?どの機能は気にしなくてよいのか?がこの本を読み進めると分かりました。</p>
<h1>仕事で使える知識が身につく</h1>
<p>Web上の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>なども最近は充実してきてますが、最初は体系的に学べる書籍がいいのではないかと思っています。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160803/20160803130814.jpg" alt="f:id:himaratsu:20160803130814j:plain" width="768" height="1024" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>この本ではタイトルにもある通り「しっかりと基本が身につく」内容になっています。</p>
<p>例えばサンプルアプリを作るときに、いきなりUI部分から始めるのではなく、先にロジックを整理して実装していくと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A5%D7%A5%BB%A5%EB%B2%BD">カプセル化</a>された良いコードが書きやすいなど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/OJT">OJT</a>で先輩エンジニアから言われそうなことが書かれています。</p>
<p>また、上に貼った画像はActivityのライフサイクルですが、例えばここではそれぞれのメソッドでは何をすべきか、何を意識すべきかが厚く書かれるなど、仕事でやる上では理解しておくべきポイントはしっかり書かれています。</p>
<p>そのため難しい部分は何度か読まないと理解できなかったりはしますが、しっかり理解できれば実戦でも良いコードが書けると思います。</p>
<h1>ありがたいサンプルコードつき</h1>
<p>本書で登場するサンプルアプリの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>は<a href="http://www.sbcr.jp/products/4797384505.html">こちらのページ</a>からDLして動かせます。</p>
<p>基本的に本の中で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>はすべて紹介されているのですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android%20Studio">Android Studio</a>でサンプルコードを開いておくと、メソッド間をジャンプしながら処理を追えたりなどして便利です。</p>
<p>自分は本に出ているコードを写経しながら勉強する派なのですが、自分の書いたコードで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>エラーが出て原因が分からないときにとても助かりました。</p>
<h1>まとめ</h1>
<p>自分はしっかり読んで理解しながら進めていきましたが、とりあえず動かしたいばの方はサンプルコードを動かしながら勉強していくこともできます。</p>
<p>『基本から身につく<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>開発入門』は、これから<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>に入門する方にピッタリな本だと思いました。</p>
<p>夏休みの間に勉強しようと思っていた方はぜひ読んでみてください。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4797384506?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51ZAA4fKuuL._SL500_.jpg" class="hatena-asin-detail-image" alt="基本からしっかり身につくAndroidアプリ開発入門 Android Studio 2.x対応 プロが本気で教えるアプリ作りの基本「技」 (ヤフー黒帯シリーズ)" title="基本からしっかり身につくAndroidアプリ開発入門 Android Studio 2.x対応 プロが本気で教えるアプリ作りの基本「技」 (ヤフー黒帯シリーズ)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4797384506?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">基本からしっかり身につくAndroidアプリ開発入門 Android Studio 2.x対応 プロが本気で教えるアプリ作りの基本「技」 (ヤフー黒帯シリーズ)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%BF%B9%20%CD%CE%C7%B7" class="keyword">森 洋之</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/SB%A5%AF%A5%EA%A5%A8%A5%A4%A5%C6%A5%A3%A5%D6">SBクリエイティブ</a></li></ul><a href="https://www.amazon.co.jp/dp/4797384506?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
himaratsu
「売れるもマーケ 当たるもマーケ マーケティング22の法則」を読んだ
hatenablog://entry/6653812171399789912
2016-06-05T20:07:27+09:00
2022-02-24T19:50:57+09:00 売れるもマーケ 当たるもマーケ―マーケティング22の法則作者:ライズ,アル,トラウト,ジャック東急エージェンシー出版部Amazon この本は過去に実際にあったマーケティングの話をベースに、「こうしなければいけない」「こうしちゃうと死ぬ」みたいな法則をまとめている本です。一部ではマーケティングの教科書とも呼ばれているみたいです 。 自分は以前から「似たような機能をもったプロダクトは沢山あるのに、なぜこのプロダクトだけが流行るのか?」を不思議に思っていて、マーケティング系の本はたまに読んでたんですが、この本は自分の持っていた疑問の多くを解決してくれた気がします。 とても良い本だったので、自分の頭の…
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4884970233?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/41ZZ608RNAL._SL500_.jpg" class="hatena-asin-detail-image" alt="売れるもマーケ 当たるもマーケ―マーケティング22の法則" title="売れるもマーケ 当たるもマーケ―マーケティング22の法則"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4884970233?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">売れるもマーケ 当たるもマーケ―マーケティング22の法則</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%A4%A5%BA%2C%A5%A2%A5%EB" class="keyword">ライズ,アル</a>,<a href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%A6%A5%C8%2C%A5%B8%A5%E3%A5%C3%A5%AF" class="keyword">トラウト,ジャック</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%EC%B5%DE%A5%A8%A1%BC%A5%B8%A5%A7%A5%F3%A5%B7%A1%BC">東急エージェンシー</a>出版部</li></ul><a href="https://www.amazon.co.jp/dp/4884970233?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>この本は過去に実際にあった<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>の話をベースに、「こうしなければいけない」「こうしちゃうと死ぬ」みたいな法則をまとめている本です。一部では<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>の教科書とも呼ばれているみたいです 。</p>
<p>自分は以前から「似たような機能をもったプロダクトは沢山あるのに、なぜこのプロダクトだけが流行るのか?」を不思議に思っていて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>系の本はたまに読んでたんですが、この本は自分の持っていた疑問の多くを解決してくれた気がします。</p>
<p>とても良い本だったので、自分の頭の中を整理する意味も込めてまとめてみます。</p>
<h2>その分野の一番手になれ</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>の勝ちパターンというのは決まっていて、それはその分野の「一番手」になること。「日本で一番高い山は?」という質問にはみんな答えられるけど、「じゃあ日本で二番目に高い山は?」と聞かれると誰も答えられない。覚えられるには一番になることが重要で、二番手は、たとえ実は性能が一番手よりも少し上だったとしても、顧客には覚えてもらえない。</p>
<p>一番手というのは市場に参入した最初の企業という意味ではなくて、「顧客の心に入り込んだ最初の企業」を意味している。例えば色々と機能を押しすぎて結局何ができるものか理解されなかったり、ブランド名(やプロダクト名)が複雑すぎて誰も覚えられないようなものだった場合、一番手にはなりにくい。</p>
<p>自分が狙っている分野にすでに一番手がいる場合、二番手に収まるのではなく、自分が一番手になれるカテゴリーを新しく作れば良い。本の例えを借りると「ビール」に対しては「国産ビール」、「自動車」に対しては「高級車」というようにカテゴリーを新設して、そこで勝負する。</p>
<p>一番手さえとれれば、あとはその分野を拡大していけば良い。例えば<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%C5%BB%D2%BD%F1%C0%D2">電子書籍</a> = <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kindle">Kindle</a>というイメージができたら、あとは「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%C5%BB%D2%BD%F1%C0%D2">電子書籍</a>」がとても素晴らしいということを伝えていけば自然と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kindle">Kindle</a>が売れる。これは顧客に「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kindle">Kindle</a>という製品がとても良い」と伝えるのよりも聴いてもらいやすい。</p>
<h2>別の分野をとりにいく時はブランドを分ける</h2>
<p>ある分野で一番手をとれたとして、次に別の分野に勝負にいくことがある。その場合、同じブランド名を使い回すのは悪手になることが多い。</p>
<p>例えばハーレイ・ダビットソンが自動車を発売しようとしたとする。この時、ハーレイ・ダビットソンのバイクの実績が、信頼となってそのまま生きるかと思いきや実はそうではない。顧客は「ハーレイ = バイクのメーカー」として認識しているので、ハーレイの車といわれても別に欲しくはならない。1つのブランドには1つのメッセージしか込められない(例えば<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DC%A5%EB%A5%DC">ボルボ</a>は"安全"、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%D7%A5%B7">ペプシ</a>は"若者")ので、分野ごとにブランドを立てるべき。</p>
<p>ここらへんを読んでると、自分が就活生の時の疑問を思い出しました。P&Gという会社を調べてるときに、「ファブリーズ」「JOY」「レノア」「パンパース」のような、身の回りで使ってるものが実は同じP&Gという会社で作られていることを知りました。自分としてはこれはとても不思議なことで、同じ名前で全商品出した方がブランド的に強くなるんじゃないかな?と思ってたのですが、この本でそれは良くない理由が説明されています。確かに「パンパース シャンプー」みたいな製品があったら、これオムツ!?と思って買わないかもなー、という感じで、長年の疑問が晴れました。</p>
<h2>もし二番手になった場合の戦い方</h2>
<p>一番手作戦がアツいのは分かったとして、とはいっても競合ひしめくこの世界、一番手になれない場合もある。そんな場合は「二極分化の法則」が役に立つ。<br />
二極分化の法則というのは長期的にみれば、ある分野のトップ2が競う形に落ち着くというもの。本の例えを借りると、かつては「コーク・<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%D7%A5%B7">ペプシ</a>・ロイヤルクラウン」の時代があったが、今では「コーク・<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%D7%A5%B7">ペプシ</a>」がほとんどのシェアを奪う2強時代になっているとのこと。</p>
<p>では自分が二番手の場合はどういう戦略がよいか?多くの会社では、一番手を研究してそれよりも良いものを作ろうとする。でも、実はこの方法では勝つことができない。一度心に刻まれたイメージを後から変えるのは難しいため、少し不便でも顧客は最初に心に入り込んだプロダクトを使う。</p>
<p>勝つための方法としては、「一番手の反対を行く」ということ。大人の飲み物という印象を持つコカコーラに対して<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%D7%A5%B7">ペプシ</a>が若者を狙ったように、一番手がとれてない領域をごっそり狙っていく。一番良くないのは「いまの時代のベストな食事」のように誰にも刺さらないメッセージを打つこと、である。</p>
<h2>必要以上にポジティブにふるまわず、正直にメッセージングする</h2>
<p>自分が一番良いなと思ったのがここで、本の中では「正直の法則」と呼ばれている。</p>
<p>例えば二番手の企業が「最高のサービスを提供します!」とかCMを打ってても、いや一番手の企業に勝てないから無理でしょ、みたいに顧客に思われてしまう。自分たちが二番手(と顧客に意識されている)場合は、そこを隠すのではなく、逆に認めることで勝機に繋げることができる。</p>
<p>レンタカー業界においてハーツに次いで二番手であるエイビスのうった広告メッセージは「エイビスはレンタカー業界で、ナンバーツーに過ぎません。だからこそご利用いただきたいのです。わたしたちは一生懸命頑張ります」というものだった。</p>
<p>普通企業は自分たちを良く見せようとするので、正直なメッセージは顧客の心を開かせる。そしてその上で行われたメッセージングは納得・信頼される、という話。</p>
<p>自分が面白かったのはこれを人に当てはめて考えて、自分の尊敬する人たちを思い浮かべると、知らないことがあった時に分かったフリをせずにちゃんとその場で質問するなー、ということでした。年次を積んでいくとつい格好つけて知ったかぶりをしてしまう時が自分にはあるけど、そんな自分の実力を誤魔化しても意味がなくて(しかもいずれバレる)、正直に分からないということで信頼に繋がるんだな、と胸を打たれました。</p>
<h1>まとめ</h1>
<p>実例を交えつつの説明で、法則がスラスラと頭の中に入ってくるとても良い本でした。<br />
"<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>"というと製品を広めたりする時の手法と思ってましたが、自分が会社やエンジニア業界でどう思われるかとか、セルフ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D6%A5%E9%A5%F3%A5%C7%A5%A3%A5%F3%A5%B0">ブランディング</a>とほぼ同じ話だなと思いました。仕事で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>に関わる人以外にも全員におすすめできる良著だと思います!</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4884970233?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/41ZZ608RNAL._SL500_.jpg" class="hatena-asin-detail-image" alt="売れるもマーケ 当たるもマーケ―マーケティング22の法則" title="売れるもマーケ 当たるもマーケ―マーケティング22の法則"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4884970233?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">売れるもマーケ 当たるもマーケ―マーケティング22の法則</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%A4%A5%BA%2C%A5%A2%A5%EB" class="keyword">ライズ,アル</a>,<a href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%A6%A5%C8%2C%A5%B8%A5%E3%A5%C3%A5%AF" class="keyword">トラウト,ジャック</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%EC%B5%DE%A5%A8%A1%BC%A5%B8%A5%A7%A5%F3%A5%B7%A1%BC">東急エージェンシー</a>出版部</li></ul><a href="https://www.amazon.co.jp/dp/4884970233?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<h1>関連記事</h1>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fbook%2Fiostest" title="「iOSアプリ テスト自動化入門」を読みました - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/book/iostest">himaratsu.hatenablog.com</a></cite></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fhealth%2Fchiropractic" title="健康にコードを書き続けるために骨に気をつける - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/health/chiropractic">himaratsu.hatenablog.com</a></cite></p>
<p><a href="http://himaratsu.hatenablog.com/entry/meyasubaco">http://himaratsu.hatenablog.com/entry/meyasubaco</a><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/meyasubaco">himaratsu.hatenablog.com</a></cite></p>
<p>*ユーザーの声を聴いてアプリを伸ばすためのサービスをつくってます→ <a href="https://meyasuba.co/">Meyasubaco</a></p>
himaratsu
初級者から中級者にレベルアップするためのXcodeデバッグ術
hatenablog://entry/10328537792368520513
2016-03-25T23:18:19+09:00
2022-02-24T20:50:53+09:00 効率よくiOSアプリ開発を行うために、効率よくデバッグを行いたいですよね。 このエントリでは「print文を書く以外デバッグの方法を知らなかったあの頃の自分」を初級者と定義して、自分がやってるデバッグ方法について書いてみます。 Xcodeデバッグ術 1. printを使わずに変数の中身を確認する age, name, coverImage という以下の3つの変数が宣言されています。 let age = 27 let name = "Ryosuke Hiramatsu" let coverImage = UIImage(named: "sample.jpg") これらの変数の中身をチェックしたい…
<p>効率よく<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>を行うために、効率よく<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>を行いたいですよね。</p>
<p>このエントリでは「print文を書く以外<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>の方法を知らなかったあの頃の自分」を初級者と定義して、自分がやってる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>方法について書いてみます。</p>
<h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>術</h1>
<h2>1. printを使わずに変数の中身を確認する</h2>
<p>age, name, coverImage という以下の3つの変数が宣言されています。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">let</span> <span class="synIdentifier">age</span> <span class="synIdentifier">=</span> <span class="synConstant">27</span>
<span class="synPreProc">let</span> <span class="synIdentifier">name</span> <span class="synIdentifier">=</span> <span class="synConstant">"Ryosuke Hiramatsu"</span>
<span class="synPreProc">let</span> <span class="synIdentifier">coverImage</span> <span class="synIdentifier">=</span> UIImage(named<span class="synSpecial">:</span> <span class="synConstant">"sample.jpg"</span>)
</pre>
<p>これらの変数の中身をチェックしたい時、printで出力するのでも良いですが、それでは出力する値を変えたくなった時(<code>print(age)</code>を<code>print(age*2+1)</code>に変更とか)に再度ビルドが必要になって時間がかかります。</p>
<p>printではなく、LLDBコマンドを使って確認することができます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325214853.png" alt="f:id:himaratsu:20160325214853p:plain" width="452" height="116" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>こんな感じで Breakpoint を貼って<a href="#f-d3ec0eb0" name="fn-d3ec0eb0" title="Breakpointは行番号のあたりをクリックで設定/解除できます">*1</a>、そこで処理を止めた状態で Console に以下のように入力します。</p>
<pre class="code" data-lang="" data-unlink>(lldb) po age
27
(lldb) po name
"Ryosuke Hiramatsu"</pre>
<p>単純に変数の値を出力するだけではなく、式の評価もできます。</p>
<pre class="code" data-lang="" data-unlink>(lldb) po age+1
28
(lldb) po name.characters.split(" ").map{ String($0) }.first
"Ryosuke"</pre>
<h2>2. QuickLookを使ってUIImageの中身を確認する</h2>
<p>coverImage 変数に対して、printやpoコマンドではどんな画像なのか確認できません。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">let</span> <span class="synIdentifier">coverImage</span> <span class="synIdentifier">=</span> UIImage(named<span class="synSpecial">:</span> <span class="synConstant">"sample.jpg"</span>)
</pre>
<pre class="code" data-lang="" data-unlink>// print(coverImage) とした時のコンソール出力
Optional(<UIImage: 0x14fe19460>, {640, 640})</pre>
<p>こういった場合、変数の上にマウスカーソルを合わせ、</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325215318.png" alt="f:id:himaratsu:20160325215318p:plain" width="225" height="72" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>現れたポップアップの目のアイコンをタップすることで画像が確認できます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325215428.png" alt="f:id:himaratsu:20160325215428p:plain" width="879" height="680" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h4>変数の値や画像の表示は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a>の左下のAreaからも可能</h4>
<p>変数の確認や QuickLook による画像の確認は Console の左のエリアからも可能です。</p>
<p>age や name などの変数名の横に値が出ていて一目で確認できます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325215632.png" alt="f:id:himaratsu:20160325215632p:plain" width="436" height="148" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>coverImage を選択した状態で目のアイコンをクリックして画像を表示することも可能です。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325215706.png" alt="f:id:himaratsu:20160325215706p:plain" width="713" height="791" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>単純な変数の確認であればこちらの方が便利ですね。</p>
<h2>3. 自作クラスのdescriptionをカスタマイズする</h2>
<p>例えば以下のようなクラスを作ったとします。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">class</span> <span class="synIdentifier">Person</span> {
<span class="synPreProc">let</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> <span class="synType">String</span>
<span class="synPreProc">let</span> <span class="synIdentifier">age</span><span class="synSpecial">:</span> <span class="synType">Int</span>
<span class="synPreProc">let</span> <span class="synIdentifier">coverImage</span><span class="synSpecial">:</span> <span class="synType">UIImage?</span>
<span class="synIdentifier">init</span>(name<span class="synSpecial">:</span> <span class="synType">String</span>, age<span class="synSpecial">:</span> <span class="synType">Int</span>, coverImage<span class="synSpecial">:</span> <span class="synType">UIImage?</span>) {
<span class="synIdentifier">self</span>.name <span class="synIdentifier">=</span> name
<span class="synIdentifier">self</span>.age <span class="synIdentifier">=</span> age
<span class="synIdentifier">self</span>.coverImage <span class="synIdentifier">=</span> coverImage
}
}
</pre>
<p>以下のようにPersonクラスの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>を生成します。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">let</span> <span class="synIdentifier">person</span> <span class="synIdentifier">=</span> Person(name<span class="synSpecial">:</span> <span class="synType">name</span>, age<span class="synSpecial">:</span> <span class="synType">age</span>, coverImage<span class="synSpecial">:</span> <span class="synType">coverImage</span>)
</pre>
<p>この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>のプロパティを確認しようと思って<code>print(person)</code>としてみると、Consoleには以下のように表示されます。</p>
<pre class="code" data-lang="" data-unlink>// print(person)
XcodeDebugPractice.Person</pre>
<p>これは知りたい情報ではありません。LLDBで<code>po person.name</code>などとすれば確認はできますが、少し手間がかかります。<br />
こういうシーンではクラスのログ出力をカスタマイズしましょう。</p>
<h3>CustomStringConvertibleを使う</h3>
<p>先ほどの Person クラスを編集して、以下のようにします。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">class</span> <span class="synIdentifier">Person</span><span class="synSpecial">:</span> <span class="synType">CustomStringConvertible</span> { <span class="synComment">//★</span>
<span class="synPreProc">let</span> <span class="synIdentifier">name</span><span class="synSpecial">:</span> <span class="synType">String</span>
<span class="synPreProc">let</span> <span class="synIdentifier">age</span><span class="synSpecial">:</span> <span class="synType">Int</span>
<span class="synPreProc">let</span> <span class="synIdentifier">coverImage</span><span class="synSpecial">:</span> <span class="synType">UIImage?</span>
<span class="synIdentifier">init</span>(name<span class="synSpecial">:</span> <span class="synType">String</span>, age<span class="synSpecial">:</span> <span class="synType">Int</span>, coverImage<span class="synSpecial">:</span> <span class="synType">UIImage?</span>) {
<span class="synIdentifier">self</span>.name <span class="synIdentifier">=</span> name
<span class="synIdentifier">self</span>.age <span class="synIdentifier">=</span> age
<span class="synIdentifier">self</span>.coverImage <span class="synIdentifier">=</span> coverImage
}
<span class="synComment">//★</span>
<span class="synPreProc">var</span> <span class="synIdentifier">description</span><span class="synSpecial">:</span> <span class="synType">String</span> {
<span class="synStatement">return</span> <span class="synConstant">"</span><span class="synSpecial">\(</span>name<span class="synSpecial">)</span><span class="synConstant">, </span><span class="synSpecial">\(</span>age<span class="synSpecial">)</span><span class="synConstant">"</span>
}
}
</pre>
<p>この状態で再び<code>print(person)</code>するとコンソールには以下が出力されます。</p>
<pre class="code" data-lang="" data-unlink>Ryosuke Hiramatsu, 27</pre>
<p>description で指定した値が出ています。<code>CustomStringConvertible</code>は print などで出力される値をカスタムするために用意されている Protocol です。</p>
<p>さらに、<strong>CustomStringDebugConvertible</strong> Protocol にも準拠してみます。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">class</span> <span class="synIdentifier">Person</span><span class="synSpecial">:</span> <span class="synType">CustomStringConvertible</span>,
CustomDebugStringConvertible { <span class="synComment">// ★</span>
<span class="synComment">// ... 省略 ... </span>
<span class="synPreProc">var</span> <span class="synIdentifier">description</span><span class="synSpecial">:</span> <span class="synType">String</span> {
<span class="synStatement">return</span> <span class="synConstant">"</span><span class="synSpecial">\(</span>name<span class="synSpecial">)</span><span class="synConstant">, </span><span class="synSpecial">\(</span>age<span class="synSpecial">)</span><span class="synConstant">"</span>
}
<span class="synPreProc">var</span> <span class="synIdentifier">debugDescription</span><span class="synSpecial">:</span> <span class="synType">String</span> { <span class="synComment">// ★</span>
<span class="synStatement">return</span> <span class="synConstant">"</span><span class="synSpecial">\(</span>name<span class="synSpecial">)</span><span class="synConstant">, </span><span class="synSpecial">\(</span>age<span class="synSpecial">)</span><span class="synConstant">, </span><span class="synSpecial">\(</span>coverImage<span class="synSpecial">)</span><span class="synConstant">"</span>
}
}
</pre>
<p>CustomStringDebugConvertible は<code>po</code>コマンドなどで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>プリントする際の値をカスタムできるものです。</p>
<p>他にも <a href="https://developer.apple.com/library/tvos/documentation/Swift/Reference/Swift_CustomReflectable_Protocol/index.html">CustomReflectable</a> や <a href="https://developer.apple.com/library/tvos/documentation/Swift/Reference/Swift_CustomLeafReflectable_Protocol/index.html">CustomLeafReflectable</a>、<a href="https://developer.apple.com/library/tvos/documentation/Swift/Reference/Swift_CustomPlaygroundQuickLookable_Protocol/index.html">CustomPlaygroundQuickLookable</a> などが用意されていますので興味のある方は調べてみてください。</p>
<h2>4. Breakpointをカスタマイズする</h2>
<p>Breakpoint をもっと便利に使いましょう。例えば Loop で特定の条件の時だけ止めたかったり、あるいは処理は止めずに Breakpoint を通過したら Console にログを吐きたい、というような場面があるとします。そんな時には Breakpoint のカスタマイズが便利です。</p>
<p>例えばこんな感じのループ文を用意して試してみます。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synStatement">for</span> i <span class="synStatement">in</span> <span class="synConstant">0</span><span class="synIdentifier">...</span><span class="synConstant">50</span> {
print(i)
}
</pre>
<p>ブレイクポイントを右クリックして「Edit Breakpoint」を選択し、</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325221924.png" alt="f:id:himaratsu:20160325221924p:plain" width="276" height="119" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p><code>condition</code>に条件を入れます。今回は<strong>「i==22の時のみ止まる」</strong>ように設定してます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325221955.png" alt="f:id:himaratsu:20160325221955p:plain" width="464" height="156" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>この状態で実行すると、i==22のループの時のみ Breakpoint で処理が止まります。特定条件の時に変数の値を確認したい場合などに便利ですね。</p>
<h4>おまけ:ブレイク時に音を出して<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>する</h4>
<p>Breakpoint では「ブレイク時にどんなOutputをするか」もカスタム可能です。</p>
<p>例えば<strong>「i==22の時だけ変数の値を確認したい。でも処理は止めずに続けたくて、値の内容は音声で確認したい」</strong>という場合は以下のように設定します。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325222529.png" alt="f:id:himaratsu:20160325222529p:plain" width="472" height="282" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>これで実行すると「22 hit!」という音声が(おそらくsayコマンドで)発声され、下の「Automatically continue after evaluating actions」にチェックをつけているため処理は止まらずに継続されます。</p>
<p>いろんな特殊条件で発生する不具合を調査する際など、Condition をうまく使うことで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>を効率的に行うことができます。ちなみに自分は実プロジェクトで音声<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>を使ったことはありませんw</p>
<h2>5. アプリ内に保存したデータを確認する</h2>
<p>NSUserDefaults や Document <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リなどに保存したデータの中身を確認する方法です。<br />
例えば以下のコードで値や画像を保存したとします:</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synComment">// NSUserDefaultsに値を保存</span>
<span class="synPreProc">let</span> <span class="synIdentifier">defaults</span> <span class="synIdentifier">=</span> NSUserDefaults.standardUserDefaults()
defaults.setObject(<span class="synConstant">"@himara2"</span>, forKey<span class="synSpecial">:</span> <span class="synConstant">"account"</span>)
defaults.synchronize()
<span class="synComment">// Diskに画像を保存</span>
<span class="synStatement">if</span> <span class="synPreProc">let</span> <span class="synIdentifier">path</span> <span class="synIdentifier">=</span> NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .AllDomainsMask, <span class="synConstant">true</span>).first,
coverImage <span class="synIdentifier">=</span> coverImage {
<span class="synPreProc">let</span> <span class="synIdentifier">targetPath</span> <span class="synIdentifier">=</span> path.stringByAppendingString(<span class="synConstant">"/sample_data.jpg"</span>)
<span class="synStatement">if</span> <span class="synPreProc">let</span> <span class="synIdentifier">data</span> <span class="synIdentifier">=</span> UIImageJPEGRepresentation(coverImage, <span class="synConstant">0.5</span>) {
<span class="synPreProc">let</span> <span class="synIdentifier">success</span> <span class="synIdentifier">=</span> data.writeToFile(targetPath, atomically<span class="synSpecial">:</span> <span class="synType">true</span>)
print(success)
}
}
</pre>
<p>保存されたデータを確認してみます。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> > Window > Organizer と選択して Organizer を開きます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325223309.png" alt="f:id:himaratsu:20160325223309p:plain" width="778" height="507" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>左メニューでアプリを実行したデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>を選択して、対象のアプリを選択します。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325223343.png" alt="f:id:himaratsu:20160325223343p:plain" width="778" height="507" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>設定ボタンから「Download Container...」を選択し、適当な場所に保存します。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325223425.png" alt="f:id:himaratsu:20160325223425p:plain" width="220" height="94" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>xcappdata 拡張子のファイルが保存されますので、右クリックして「パッケージの内容を表示」します。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325223607.png" alt="f:id:himaratsu:20160325223607p:plain" width="337" height="178" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>中身はこのようになっています。<br />
Documents/ に保存した画像ファイル(sample_data.jpg)が存在しているのが分かります。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325224142.png" alt="f:id:himaratsu:20160325224142p:plain" width="380" height="201" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>さらに、Library/Preferences/ 下のplistの中身をみると、</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160325/20160325224304.png" alt="f:id:himaratsu:20160325224304p:plain" width="410" height="70" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>このように NSUserDefaults の値が保存されていることが分かります。</p>
<p>保存した内容を取り出すコードを実装するのでも良いのですが、ハマった時は原因が切り分けが大事なので、実際に保存されている情報を目視できるのは意味のあることだと思っています。</p>
<h1>まとめ</h1>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>手法に関する記事は以外と少なく、自分が最初に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>を始めた時は NSLog を大量に埋めて頑張ってました。<br />
今回紹介したような<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>手法を知ってからスピーディに開発できるようになったな、と思ったのでこのような記事を書かせていただきました。</p>
<p>何か間違ってる部分や、他に良い<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>方法などご存知でしたらぜひ教えてください :)</p>
<p>みなさんの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>ライフに少しでもお役立ちできれば光栄です。</p>
<h1>サンプルコード</h1>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fhimaratsu%2FXcodeDebugPractice" title="GitHub - himaratsu/XcodeDebugPractice: iOS app debug using Xcode efficiently" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/himaratsu/XcodeDebugPractice">github.com</a></cite></p>
<p>今回引用したコードはすべてこちらでお試しいただけます。</p>
<h1>こちらもいかがですか?</h1>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fplayground" title="XcodeのPlaygroundをつかってUIの実装をサクサク試す - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/playground">himaratsu.hatenablog.com</a></cite></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fswift%2Fextension" title="iOSアプリの開発効率をあげるSwiftの便利Extension - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/swift/extension">himaratsu.hatenablog.com</a></cite></p>
<div class="footnote">
<p class="footnote"><a href="#fn-d3ec0eb0" name="f-d3ec0eb0" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">Breakpointは行番号のあたりをクリックで設定/解除できます</span></p>
</div>
himaratsu
XcodeのPlaygroundをつかってUIの実装をサクサク試す
hatenablog://entry/10328537792367562079
2016-03-19T01:18:26+09:00
2022-02-24T19:50:48+09:00 2018/04/10 追記 一部コードが古くなっています。 Xcode 9.3, Swift 4.1 の環境では以下のコードで動作します。 import PlaygroundSupport let vc = UIViewController() vc.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480) vc.view.backgroundColor = .lightGray PlaygroundPage.current.needsIndefiniteExecution = true PlaygroundPage.current.li…
<p><strong>2018/04/10 追記</strong></p>
<p>一部コードが古くなっています。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> 9.3, Swift 4.1 の環境では以下のコードで動作します。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">import</span> PlaygroundSupport
<span class="synPreProc">let</span> <span class="synIdentifier">vc</span> <span class="synIdentifier">=</span> UIViewController()
vc.view.frame <span class="synIdentifier">=</span> CGRect(x<span class="synSpecial">:</span> <span class="synConstant">0</span>, y<span class="synSpecial">:</span> <span class="synConstant">0</span>, width<span class="synSpecial">:</span> <span class="synConstant">320</span>, height<span class="synSpecial">:</span> <span class="synConstant">480</span>)
vc.view.backgroundColor <span class="synIdentifier">=</span> .lightGray
PlaygroundPage.current.needsIndefiniteExecution <span class="synIdentifier">=</span> <span class="synConstant">true</span>
PlaygroundPage.current.liveView <span class="synIdentifier">=</span> vc.view
</pre>
<hr>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> の Playground を久しぶりに使ってみて、UIの実装とかこれでやると便利だな、と思ったのでやり方をまとめてみます。</p>
<p>やりたい完成系はこんな感じ:
<img src="https://i.gyazo.com/05957d0dffaf5c49d86b48ab119529d0.gif" alt="" /></p>
<p>左に書いた TableView のコードが右で即時反映されてます。</p>
<h1>前置き:そもそもPlaygroundとは</h1>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160318/20160318235944.png" alt="f:id:himaratsu:20160318235944p:plain" width="876" height="239" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>Playground というのは <a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> 6 から登場した Swift の REPL 環境です。<br />
上記の画像のように、コードを書くと実行結果がビルドすることなしに即時に表示されます。Swift の文法を試せすのにもってこいで、自分も入門したての頃にはよく使ってました。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a> の公式の Swift ドキュメント「<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language">The Swift Programming Language</a>」の概要部分ではドキュメントが Playground として実装されていて、実際に値を変えたり動かしながら確認することができます。(<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html">ここのページ</a>の Download Playground から落とせます)</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160319/20160319000548.png" alt="f:id:himaratsu:20160319000548p:plain" width="1024" height="611" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>実際に動かせるドキュメントとして Playground はとても優秀で、読んで→書いてとやってたのが同時に可能です。最近流行りの<a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a>ライブラリである<a href="https://github.com/ReactiveX/RxSwift">RxSwift</a>でもPlayground形式のドキュメントが同梱されたりしています。</p>
<h1>PlaygroundでUIをつくる</h1>
<p>3月頭に <a href="http://www.tryswiftconf.com/">try! Swift</a> というSwiftのカンファレンスに参加したんですが、そこで驚いたのが海外のスピーカーの方がよく Playground を使ってることでした。<br />
文法のデモはもちろん、アニメーションの調整(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%F3%A5%B9%A5%BF%A1%BC%A5%DC%A1%BC%A5%EB">モンスターボール</a>を投げると回転して爆発して<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DD%A5%B1%A5%E2%A5%F3">ポケモン</a>が登場する)や TableView の実装まで、Project ではなくて Playground でサクサクと進めてました。</p>
<p>自分は最近はほとんど Playground 使ってなくて、どれくらい便利なのかなーと思って試してみたやり方と感想をまとめます。</p>
<h2>XCPlaygroundをimportする</h2>
<p>下記のように記述して、XCPlayground を import します。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">import</span> XCPlayground
</pre>
<h2>ライブ表示するviewを指定する</h2>
<p>次に右側にライブ表示する view を指定します。<br />
今回は UITableViewController を root とした NavigationController を表示するので、以下のように指定します。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">let</span> <span class="synIdentifier">tableVC</span> <span class="synIdentifier">=</span> UITableViewController()
<span class="synPreProc">let</span> <span class="synIdentifier">navigationController</span> <span class="synIdentifier">=</span> UINavigationController(rootViewController<span class="synSpecial">:</span> <span class="synType">tableVC</span>)
XCPlaygroundPage.currentPage.needsIndefiniteExecution <span class="synIdentifier">=</span> <span class="synConstant">true</span>
XCPlaygroundPage.currentPage.liveView <span class="synIdentifier">=</span> navigationController.view
</pre>
<h2>Assistant Editorを開く</h2>
<p>viewはREPLで表示されるコンソール<strong>ではなく</strong>、Assistant Editor で開いた Timeline に表示されます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160319/20160319011142.png" alt="f:id:himaratsu:20160319011142p:plain" width="1024" height="623" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>ここまでで view が表示できてるはずです。</p>
<h2>実装を書いていく</h2>
<p>試した内容としては、カスタムな UITableView を書いて、その view を Playground でライブ表示していきました。<br />
Playground につらつらと書いていって、以下のように記述しました。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">import</span> UIKit
<span class="synStatement">final</span> <span class="synPreProc">class</span> <span class="synIdentifier">MyTableViewController</span><span class="synSpecial">:</span> <span class="synType">UITableViewController</span> {
<span class="synComment">// ... MyTableViewControllerの実装をここに</span>
}
<span class="synPreProc">let</span> <span class="synIdentifier">tableVC</span> <span class="synIdentifier">=</span> MyTableViewController(style<span class="synSpecial">:</span> .Plain,
items<span class="synSpecial">:</span> <span class="synType">people</span>,
cellStyle<span class="synSpecial">:</span> .Subtitle,
editable<span class="synSpecial">:</span> <span class="synType">true</span>) { cell, item <span class="synStatement">in</span>
cell.textLabel?.text <span class="synIdentifier">=</span> item.name
cell.detailTextLabel?.text <span class="synIdentifier">=</span> item.city
}
tableVC.title <span class="synIdentifier">=</span> <span class="synConstant">"Person"</span>
<span class="synPreProc">let</span> <span class="synIdentifier">navigationController</span> <span class="synIdentifier">=</span> UINavigationController(rootViewController<span class="synSpecial">:</span> <span class="synType">tableVC</span>)
navigationController.view.frame <span class="synIdentifier">=</span> CGRectMake(<span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">320</span>, <span class="synConstant">480</span>)
<span class="synPreProc">import</span> XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution <span class="synIdentifier">=</span> <span class="synConstant">true</span>
XCPlaygroundPage.currentPage.liveView <span class="synIdentifier">=</span> navigationController.view
</pre>
<p>こんな感じで書いていくと、以下のように表示されます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160319/20160319002149.png" alt="f:id:himaratsu:20160319002149p:plain" width="1024" height="607" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>いい感じですね!</p>
<p>コードを修正するたびに変更が右側のViewに反映されていくので、とても効率よく実装ができます。</p>
<p><img src="https://i.gyazo.com/05957d0dffaf5c49d86b48ab119529d0.gif" alt="" /></p>
<h1>サンプルコード</h1>
<p>今回試した内容はこちらの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>にまとめています。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fhimaratsu%2FSwiftyTableViewControllerPlayground" title="GitHub - himaratsu/SwiftyTableViewControllerPlayground" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/himaratsu/SwiftyTableViewControllerPlayground">github.com</a></cite></p>
<p>(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> 7.2, Swift 2.1 でつくりました)</p>
<h1>まとめ</h1>
<p>Playground で UI を実装するのはとても快適でした。ビルド時間はいらないし、「ビルドするぞ」と切り替える回数が少ないのも捗ります。<br />
現在はタッチイベントなどは検知できませんが、次の <a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> のバージョンでは UITapGestureRecognizer などにも対応するようで、それができると一気に可能性が広がる気がします。</p>
<p>一方で、storyboard とか xib を使っての実装とは相性はよくありません。try! Swiftのスピーカー陣は storyboard 使わない派の人が多かったので、ここは気にしてないのかもしれませんね。<br />
自分は storyboard 積極的に使ってく派ですが、アニメーションや View の部品をコードだけで実装するケースでは今後 Playground で作ろうと思いました。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> Playground は文法の確認や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A5%E9%A5%AF%A5%C6%A5%A3%A5%D6">インタラクティブ</a>なドキュメントだけでなく、UI の実装にも便利そうという話でした。 みなさまの Playground Life のお助けになれば光栄です :)</p>
himaratsu
try! Swiftで特に復習したいセッションまとめ #tryswiftconf
hatenablog://entry/10328537792366233802
2016-03-18T23:50:42+09:00
2022-02-24T20:50:58+09:00 3月2-4日の3日間、try! Swift に参加してきました。 #tryswiftconf 💖 pic.twitter.com/4jtb6XEF1J— try! Swift Tokyo (@tryswiftconf) 2016年3月4日 try! Swift とは東京渋谷で開催された、世界中から集まった Swift デベロッパーが知識や技術を共有することを目的としたカンファレンスです。 try! Swift セッションの内容は自分にとって難しいものが多く、明日から使える tips & tricks みたいなのは少なくて、プログラミング言語の中でSwiftはこういう特性があるよ、そしてそれを活…
<p>3月2-4日の3日間、try! Swift に参加してきました。</p>
<p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="und" dir="ltr"><a href="https://twitter.com/hashtag/tryswiftconf?src=hash&ref_src=twsrc%5Etfw">#tryswiftconf</a> 💖 <a href="https://t.co/4jtb6XEF1J">pic.twitter.com/4jtb6XEF1J</a></p>— try! Swift Tokyo (@tryswiftconf) <a href="https://twitter.com/tryswiftconf/status/705680966921007104?ref_src=twsrc%5Etfw">2016年3月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p>
<p>try! Swift とは東京渋谷で開催された、世界中から集まった Swift <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D9%A5%ED%A5%C3%A5%D1">デベロッパ</a>ーが知識や技術を共有することを目的としたカンファレンスです。</p>
<p><a href="http://www.tryswiftconf.com/">try! Swift</a></p>
<p>セッションの内容は自分にとって難しいものが多く、明日から使える tips & tricks みたいなのは少なくて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0%B8%C0%B8%EC">プログラミング言語</a>の中でSwiftはこういう特性があるよ、そしてそれを活かしてこんなこともできるよね!みたいな、Swiftそのものの話や言語のポテンシャルに言及するものが多かった気がします。</p>
<h1>振り返り勉強したいセッション</h1>
<h2>一度聞いただけでは全然理解できてない</h2>
<p>そんな濃いセッションだったので、一度聞いただけでは2割も理解できてないです。<br />
そこで、個人的に振り返って勉強したい順にセッションをまとめてみます。</p>
<p>業務やプライベートの実際のプロダクトで試すのが一番理解が進められると思ったので、そういう意味での試しやすい順番に並べました。</p>
<h2>1.既存のコードをもっとSwiftyにする系セッション</h2>
<p>会社ではフルSwiftで書いてるけど、まだまだ言語の特性を活かせる箇所が多く見つかったので。</p>
<h3>Blending Cultures</h3>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>, 関数型, Protocol指向の考えをミックスしてSwiftyなコードを書く</li>
<li>実際のコードベースでプレゼンが進められたので理解しやすく、抽象化の勉強になる</li>
<li>参考リンク
<ul>
<li><a href="http://niwatako.hatenablog.jp/entry/2016/03/02/160011">try! Swift 文化を調和させる #tryswiftconf Day1-8 - niwatakoのはてなブログ</a></li>
<li><a href="http://qiita.com/masashi-sutou/items/7d2953d86397123e84e6">「文化を調和させる」をやってみる - Try “Blending Culture” - Qiita</a></li>
</ul>
</li>
</ul>
<h3>Table View Controllers in Swift</h3>
<ul>
<li>TableViewController のコードを Swifty に、 Generic にする</li>
<li>その TableVC に Configuration を渡すだけでコンテンツの表示がなされる</li>
<li>Chris さんにはQAセッションでいくつか質問したので、その内容含めて復習する</li>
<li>参考リンク
<ul>
<li><a href="http://niwatako.hatenablog.jp/entry/2016/03/03/181127">try! Swift SwiftらしいTable View Controllerの使い方 #tryswiftconf Day2-11 - niwatakoのはてなブログ</a></li>
<li><a href="https://github.com/himaratsu/SwiftyTableViewControllerPlayground">GitHub - himaratsu/SwiftyTableViewControllerPlayground</a></li>
</ul>
</li>
</ul>
<h3>Hipster Swift</h3>
<ul>
<li><a href="http://nshipster.com/">NSHipster</a> の中の方による Swift の tips集</li>
<li><code>@autoclosure</code>や<code>lazy var</code>など、理解があいまいなのでこれを機にちゃんと理解する</li>
<li>参考リンク
<ul>
<li><a href="http://niwatako.hatenablog.jp/entry/2016/03/04/131157">try! Swift Swiftヒップスター #tryswiftconf Day3-4 - niwatakoのはてなブログ</a></li>
<li><a href="http://krakendev.io/blog/hipster-swift">Hipster Swift: Demystifying the Mysterious — KrakenDev</a></li>
</ul>
</li>
</ul>
<h2>2.<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>やテストをしっかり学ぶ系セッション</h2>
<p>特にテストはいまあまり書けてないので重点的に復習したい。</p>
<h3>Swift compiler integration in LLDB</h3>
<ul>
<li>LLDB をつかって<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>をもっと効率よく</li>
<li><code>p</code>や<code>po</code>コマンドの他、<code>CustomDebugConvertible</code>など</li>
<li>参考リンク
<ul>
<li><a href="http://niwatako.hatenablog.jp/entry/2016/03/03/151617">http://niwatako.hatenablog.jp/entry/2016/03/03/151617</a></li>
<li><a href="https://developer.apple.com/videos/play/wwdc2014/410/">WWDC14 - Videos - Apple Developer</a></li>
<li><a href="https://developer.apple.com/videos/play/wwdc2015/402/">What's New in LLDB - WWDC15 - Videos - Apple Developer</a></li>
</ul>
</li>
</ul>
<h3>An Artsy Testing Tour</h3>
<ul>
<li>4つのアプリを題材に、テストをどう書いていこうか?という話</li>
<li>いま書いてるアプリはほぼテストないので、復習してから計画的に書く</li>
<li>参考リンク
<ul>
<li><a href="http://niwatako.hatenablog.jp/entry/2016/03/04/182144">http://niwatako.hatenablog.jp/entry/2016/03/04/182144</a></li>
</ul>
</li>
</ul>
<h3>Protocol-Oriented Programming in Networking</h3>
<ul>
<li>APIKit のようなインターフェースをいかに実装するか</li>
<li>RxSwift をつかったコードの書き方</li>
<li>APIKit, RxSwift ともに業務で書いてるアプリに導入したいのでちゃんと理解する</li>
<li>ishkawaさんの発表はいつも大変わかりやすく、発表スタイルも勉強になります</li>
<li>参考リンク
<ul>
<li><a href="http://niwatako.hatenablog.jp/entry/2016/03/03/170031">try! Swift Protocol-Oriented Programming in Networking #tryswiftconf Day2-9 - niwatakoのはてなブログ</a></li>
<li><a href="https://github.com/ishkawa/sandbox/tree/master/RxPagination">sandbox/RxPagination at master · ishkawa/sandbox · GitHub</a></li>
</ul>
</li>
</ul>
<h2>3.ワンランク上にレベルアップできそうなセッション</h2>
<p>普段コードを書くときに心がけることで、メンバーや未来の自分に意図が"伝わる"コードを書ける。</p>
<h3>The Design of Everyday Swift</h3>
<ul>
<li>「誰のためのデザイン?」という本の考えを Swift にあてはめて考える</li>
<li>private/public/internalや、メソッド名のつけかたなどで意思の伝わるコードを書く</li>
<li>意識してるつもりではあるけど、自分のコードを見直す</li>
<li>参考リンク
<ul>
<li><a href="http://niwatako.hatenablog.jp/entry/2016/03/03/130407">try! Swift Swift版「誰のためのデザイン?」 #tryswiftconf Day2-5 - niwatakoのはてなブログ</a></li>
</ul>
</li>
</ul>
<p>本も読んでみる。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4788514346?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51uEWA1B3EL._SL500_.jpg" class="hatena-asin-detail-image" alt="誰のためのデザイン? 増補・改訂版 ―認知科学者のデザイン原論" title="誰のためのデザイン? 増補・改訂版 ―認知科学者のデザイン原論"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4788514346?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">誰のためのデザイン? 増補・改訂版 ―認知科学者のデザイン原論</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/D.%20A.%20%A5%CE%A1%BC%A5%DE%A5%F3" class="keyword">D. A. ノーマン</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B7%CD%CB%BC%D2">新曜社</a></li></ul><a href="https://www.amazon.co.jp/dp/4788514346?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<h3>Learning to Read Again</h3>
<ul>
<li>コードを読むときに人はどう読んでいくのか?</li>
<li>読みやすく、かつ理解されやすいコードを書くために意識することを理解する</li>
<li>参考リンク
<ul>
<li><a href="http://niwatako.hatenablog.jp/entry/2016/03/02/115920">try! Swift 書き起こし コードリーディングについて #tryswiftconf Day1-3 - niwatakoのはてなブログ</a></li>
</ul>
</li>
</ul>
<h2>4.<a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a>を公開/貢献する系のセッション</h2>
<p>今年は自分の使ってるモジュールを切り出して公開していこうと思っているので。</p>
<h3>Creating a Library</h3>
<ul>
<li>ライブラリをつくって CocoaPods & Carthage & Swift Package Manager で配布する話</li>
<li>参考リンク
<ul>
<li><a href="http://niwatako.hatenablog.jp/entry/2016/03/03/160212">try! Swift ライブラリの開発 #tryswiftconf Day2-8 - niwatakoのはてなブログ</a></li>
<li><a href="https://github.com/tryswift/Snorlax">GitHub - tryswift/Snorlax: The ultimate lazy library. An example for being a good library citizen in Swift.</a></li>
</ul>
</li>
</ul>
<h3>Motivation based library abstraction</h3>
<ul>
<li>日常のコードから、どうやってどのような粒度で切り離して<a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a>化しているかの話</li>
<li>参考リンク
<ul>
<li><a href="http://niwatako.hatenablog.jp/entry/2016/03/04/111724">try! Swift Motivation based library abstraction #tryswiftconf Day3-1 - niwatakoのはてなブログ</a></li>
</ul>
</li>
</ul>
<h3>Contributing to open source Swift</h3>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a>のなったSwift、その概要を理解し、自分が貢献できそうな領域を見つけよう、という話</li>
<li>前半の解説部分、後半の貢献へのスタンスとコミュニティの話、どちらも最高でした</li>
<li>自分で<a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a>をいくつか公開した後、Swift のコードをよく読んでみたい</li>
<li>参考リンク
<ul>
<li><a href="http://niwatako.hatenablog.jp/entry/2016/03/04/173304">http://niwatako.hatenablog.jp/entry/2016/03/04/173304</a></li>
</ul>
</li>
</ul>
<h1>感想・全セッションを通じて思ったこと</h1>
<ul>
<li>サーバーサイド Swift の話がよく出ていくる
<ul>
<li>日本ではそんなにまだ聞かないな?と思ってたので驚いた</li>
</ul>
</li>
<li>みんな簡単なコードやプロトタイプくらいは Playground で書いている
<ul>
<li>自分も真似してちょっと使ってみたけど大変便利。今後も使っていきたい</li>
</ul>
</li>
<li>テストについてはみんな悩んでいる
<ul>
<li>テストのセッションの最後のQAで、「テストの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%A9%BF%F4">工数</a>をどう理解してもらえるか」「UIテストをどう考えてるか」という質問が出て、万国共通の悩みなんだなと思った</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>にあった「テストコードを書くことで、テストが書ける状態に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>されるのが大事」というのが自分の考えに近い</li>
</ul>
</li>
<li>Protocol Extension, Functional Programming が頻出
<ul>
<li>意識して使えてなくて、Objective-Cy なコードを書いてしまってるなぁ、と反省</li>
</ul>
</li>
<li>本質的な話が多かった
<ul>
<li>こんなライブラリがありまして、みたいな話はほぼなくて、すべてに共通する考え方・実装の仕方の話が多かった</li>
<li>「明日からこのライブラリ使うぞ!」とはならず、「自分の普段書いてるコードはどうなのか」と振り返る機会になった</li>
</ul>
</li>
</ul>
<h1>まとめ</h1>
<p>3日間とても熱く濃い時間をすごせました。</p>
<p>普段ほとんど Swift を書いてるのに理解できない話がとても多く、悔しい思いもしましたが、これをエネルギーにしてひとつずつキャッチアップしていこうと思います。</p>
<p>スピーカーのみなさま、運営スタッフのみなさま、そして素晴らしい会場を提供してくださった<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%A4%A5%D0%A1%BC%A5%A8%A1%BC%A5%B8%A5%A7%A5%F3%A5%C8">サイバーエージェント</a>さん、本当にありがとうございました!</p>
himaratsu
第26回はSupershipで開催! #potatotips で発表されたiOSのtipsまとめ
hatenablog://entry/10328537792363754595
2016-02-17T23:53:06+09:00
2022-02-24T19:50:57+09:00 約1年ぶりに #potatotips に参加させていただきました。 第26回目となる今回は Supership株式会社 さん主催での開催でした。 potatotips は1人5分の持ち時間でtipsを共有する勉強会です。 元々はクックパッドさんが始めた勉強会ですが、現在は様々な会社にて開催されています。 第26回で発表された8つのiOSのtipsをまとめます!
<p>約1年ぶりに #potatotips に参加させていただきました。<br />
第26回目となる今回は <a href="https://supership.jp/">Supership株式会社</a> さん主催での開催でした。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160217/20160217225105.jpg" alt="f:id:himaratsu:20160217225105j:plain" width="1024" height="768" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>potatotips は1人5分の持ち時間でtipsを共有する勉強会です。<br />
元々は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%C3%A5%AF%A5%D1%A5%C3%A5%C9">クックパッド</a>さんが始めた勉強会ですが、現在は<a href="http://connpass.com/series/652/">様々な会社にて開催</a>されています。</p>
<p>第26回で発表された8つの<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>のtipsをまとめます!</p>
<h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> Tips</h1>
<h3>Can we live in a pure Swift World?</h3>
<ul>
<li><a href="https://twitter.com/TachibanaKaoru">@TachibanaKaoru</a> さん</li>
<li>新しいアプリを書くとき、いまならSwiftで書きたいですよね?</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Generics">Generics</a> や Tuple、Protocol Extension などの Swift の機能
<ul>
<li>これらは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Objective-C">Objective-C</a>のコードから呼べない</li>
<li>さらに、selector で指定することができない</li>
<li>Tupleを返すメソッドを実装し、selector 指定してコールすると落ちる
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>は通るけど実行時に unrecognized selector</li>
</ul>
</li>
</ul>
</li>
<li>UIKit を使っている限り、Pure Swift とはいえない。Swift UI Framework が欲しいですね</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/key/6pBCgU54khdypR" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe></li>
</ul>
<h3>5分で分かるTextKit</h3>
<ul>
<li><a href="https://twitter.com/hayashi311">@hayashi311</a> さん</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 7から TextView は TextKit ベースになった</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%F3%A5%C0%A5%EA%A5%F3%A5%B0">レンダリング</a>とは、文字列を Bitmap 画像に変換すること。この仕組みを考える
<ul>
<li>文字+フォント →「グリフ」、グリフ + レイアウト → 「文章」という感じで構築</li>
<li>これを UITextKit で置き換えて理解していく</li>
</ul>
</li>
<li>自前で実装できそうな気がするが、実際やろうとすると落とし穴が多い</li>
<li>UITextView に感謝</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/key/7VIJ0Bwm9BYlNf" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe></li>
</ul>
<h3>PUSH通知の許可をよりもらうためのUI考察など</h3>
<ul>
<li><a href="https://twitter.com/yoneapp">@yoneapp</a> さん</li>
<li>Push 通知サービスはどこを使おうか?
<ul>
<li><a href="https://onesignal.com/">OneSignal</a></li>
<li>特徴
<ul>
<li>完全無料、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%D7%A5%E9%A5%C3%A5%C8%A5%D5%A5%A9%A1%BC%A5%E0">マルチプラットフォーム</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>が使える、ドキュメントが良い</li>
</ul>
</li>
<li>不明な点
<ul>
<li>Push通知の配信速度、ビジネスモデル(<a href="https://www.parse.com/">Parse</a>のように終了しないか不安)</li>
</ul>
</li>
</ul>
</li>
<li>Pushを許可してもらうタイミング
<ul>
<li>1: 唐突に出す</li>
<li>2:「はじめる」みたいなボタンを押したら唐突に出す</li>
<li>3: 擬似アラートを出してから出す</li>
<li>4: なにかアクションした時に自前で「通知をオンにしてください」→OK押したら出す</li>
<li>結論としては1がコストもかからないし良さそう。やってるサービスも多い</li>
</ul>
</li>
<li>考察をまとめたブログはこちら → <a href="http://blog.yoneapp.com/entry/2016/01/21/232451">http://blog.yoneapp.com/entry/2016/01/21/232451</a></li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/key/87z2QlOPsgHQZf" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe></li>
</ul>
<h3>NSURLProtectionSpace Authentication Methods</h3>
<ul>
<li><a href="https://twitter.com/niwatako">@niwatako</a> さん</li>
<li><code>URLSession:didReceiveChallenge:completionHandler:</code>は、認証が必要な通信で呼ばれるメソッド
<ul>
<li>この <a class="keyword" href="http://d.hatena.ne.jp/keyword/delegate">delegate</a> が呼ばれたら、認証に必要な情報をもった NSURLCredential を返す</li>
<li><code>challenge.protectionSpace.authenticationmethod</code> で求められている認証の種類を確認できる
<ul>
<li>認証の7つのパターンの解説</li>
</ul>
</li>
<li>大きく対応方法を分けると、以下の通り:
<ul>
<li>Basic, Digest, Negotiate, NTLM → ユーザー名とパスワードを使って NSURLCredential を作って返す</li>
<li>ClientCertificate → 長すぎるので続きは yidev で</li>
<li>ServerTrust → .PerformDefaultHandling を指定しておけば OS がよしなにやってくれる</li>
</ul>
</li>
</ul>
</li>
<li>続きは yidev で!</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/key/yXNmldjqpvldXw" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe></li>
</ul>
<h3>皆に相談したい「私の現場での試行錯誤後の<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>開発方針」</h3>
<ul>
<li><a href="https://twitter.com/satoshi0212">@satoshi0212</a> さん</li>
<li>開発の方針
<ul>
<li>Storyboard, xib は使わずコードで実装する</li>
<li>SizeClass は使用してない、AutoLayout は少し使用する</li>
<li>viewDidLoad 内でレイアウト生成</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a> のライブラリは控えめで、直接プロジェクトに追加する</li>
<li>重い画面の場合は viewDidAppear で生成(表示がすぐなのでサクサク出る)</li>
</ul>
</li>
<li>メンバー構成としてはデザイナーなしで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE">プログラマ</a>4人でやってる</li>
<li>質疑にて
<ul>
<li>前職(BtoB)のときは storyboard 使わずにコードを書いてたが、現在(BtoC)はできるだけ storyboard を使ってる</li>
<li>デザイナーが触るかどうかで大きく違うかもしれない</li>
</ul>
</li>
<li><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fqiita.com%2Fsatoshi0212%2Fitems%2F327639ca4d1e64a5a1f3" title="私の現場での試行錯誤後のiOS開発方針 - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://qiita.com/satoshi0212/items/327639ca4d1e64a5a1f3">qiita.com</a></cite></li>
</ul>
<h3>脱swift初心者するための2つのきっかけ</h3>
<ul>
<li><a href="https://twitter.com/mogmet">@mogmet</a>さん</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%D8%BF%F4%B7%BF%B8%C0%B8%EC">関数型言語</a>を使おう
<ul>
<li>swiftは関数型もサポートしている</li>
<li>filter (配列から該当する要素だけを取り出す)</li>
<li>indexOf(配列にその中の要素を渡すとindexを返す)</li>
<li>map(配列のそれぞれの要素に対して処理を行う)</li>
</ul>
</li>
<li>{}を減らそう
<ul>
<li><code>if let</code> → <code>guard let ... else</code> に書き換える</li>
<li>where句を使う</li>
</ul>
</li>
<li>関数型で短く書こう、{}を減らして保守性を高めよう</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/key/AtEUxiNp5tioSC" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe></li>
</ul>
<h3>HTTPリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トをフックしてハック</h3>
<ul>
<li><a href="https://twitter.com/yukiasai">@yukiasai</a> さん</li>
<li><a href="https://github.com/yukiasai/Gecco">Gecco</a> がもうすぐ1000スターなので後押ししてほしい</li>
<li>WebAPI がまだできてないけど、アプリ側の実装をはじめないといけない場合がある
<ul>
<li>ライブラリを作った</li>
<li>path を指定して、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%C6%A1%BC%A5%BF%A5%B9%A5%B3%A1%BC%A5%C9">ステータスコード</a>や body をモックできるライブラリ</li>
<li>マネー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%A9%A5%EF">フォワ</a>ード社内でも使われている</li>
</ul>
</li>
<li>NSURLProtocol をつかって書き換えている</li>
<li>ライブラリのソースを見ながら解説</li>
<li><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fyukiasai%2FKagee" title="GitHub - yukiasai/Kagee: Easily way to write a stub for the network request" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></li>
</ul>
<h3>古き良き sendAction</h3>
<ul>
<li><a href="https://twitter.com/tokorom">@tokorom</a> さん</li>
<li>UIApplication#sendAction、使ってる人はいますか?</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 2からある</li>
<li><code>app.sendAction("hoge:", to: XXX, from: sender, forEvent: nil)</code>
<ul>
<li>to に <a class="keyword" href="http://d.hatena.ne.jp/keyword/nil">nil</a> を指定した場合、firstResponder から遡って呼んでくれる</li>
<li>ViewControllerが入り組んでいて、階層が深い場所の UIButton 押されたときとかに良い</li>
</ul>
</li>
<li>良い部分
<ul>
<li>レスポンダチェーンされる
<ul>
<li>奥まった階層でも発火できるし、受け流すこともできる</li>
</ul>
</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Cocoa">Cocoa</a>の根幹となる仕組みなので時代に左右されにくい</li>
</ul>
</li>
<li>ダメなところ
<ul>
<li>インターフェースが古い(文字列指定、 selector)</li>
<li>引数に特定のObjectを渡しづらい</li>
</ul>
</li>
<li><script async class="speakerdeck-embed" data-id="df6a83fc875a4c5a86b0f578a90634ba" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h1>告知</h1>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> Developers Conference Japan 2016</h3>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fiosdc.jp%2F" title="iOSDC Japan 2021" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://iosdc.jp/">iosdc.jp</a></cite></p>
<ul>
<li>2016年8月<a class="keyword" href="http://d.hatena.ne.jp/keyword/20%C6%FC">20日</a>開催</li>
<li>開催までのスケジュール予定
<ul>
<li>5月: チケット販売開始 / <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>募集開始</li>
<li>6月上旬: <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>募集〆切</li>
<li>6月下旬: タイムテーブル決定</li>
</ul>
</li>
<li>スポンサーになってくれる企業を募集中</li>
</ul>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%E6%A4%C8%A4%EA%C0%A4%C2%E5">ゆとり世代</a>エンジニア交流会</h3>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fconnpass.com%2Fevent%2F26812%2F" title="【出張】ゆとり世代エンジニア交流会【ひな祭り】 (2016/03/04 19:30〜)" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://connpass.com/event/26812/">connpass.com</a></cite></p>
<ul>
<li>28歳以下くらいのゆとりエンジニアの集い</li>
<li>今回主催していただいた<a class="keyword" href="http://d.hatena.ne.jp/keyword/Supership">Supership</a>株式会社にて行われる</li>
<li>気持ちがゆとりなら参加可能</li>
</ul>
<h1>まとめ</h1>
<p>potatotips には約1年ぶりの参加となりましたが、以前と変わらぬ雰囲気で楽しく tips が発表されていました。<br />
自分はまとめてない<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>側の発表ではKotlinについて多く触れられており、Swift と似ている部分が多そうだと思ったので書いてみたくなりました。</p>
<p>今回の <a class="keyword" href="http://d.hatena.ne.jp/keyword/Supership">Supership</a> さんのように、potatotips を開催したい企業を募集しているようです。<br />
自分の会社でぜひ、という場合は <a href="https://twitter.com/tokorom">@tokorom</a> さんに連絡すれば良いようです。</p>
<p>発表者のみなさん、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Supership">Supership</a> のみなさん、本日はありがとうございました!</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20160217/20160217233435.jpg" alt="f:id:himaratsu:20160217233435j:plain" width="768" height="1024" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a> の tips のまとめはこちら</h1>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fqiita.com%2Fyimajo%2Fitems%2Fada2336f02c47f43ed76" title="potatotips #26に参加した - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://qiita.com/yimajo/items/ada2336f02c47f43ed76">qiita.com</a></cite></p>
<h1>関連記事</h1>
<ul>
<li>過去に開催されたポテチのまとめ記事はこちらです
<ul>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips1">クックパッドのLT会に参加してきたのでiOSのtipsをまとめる</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips2">第2回 #potatotips に参加してきたのでiOSのtipsをまとめる</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips3">第3回はヤフー開催! #potatotips で発表されたiOSのtipsまとめ</a></li>
<li><a href="http://himaratsu.hatenablog.com/search?q=potatotips">And more...</a></li>
</ul>
</li>
</ul>
himaratsu
iOSアプリの開発効率をあげるSwiftの便利Extension
hatenablog://entry/6653458415126589606
2015-11-01T23:11:45+09:00
2022-02-24T19:50:53+09:00 Swift の Extension を使うと既存クラスや自作クラスを拡張することができます。 会社や個人のプロジェクトでいつも使っている便利な拡張コードをまとめてみます。
<p><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html">Swift の Extension</a> を使うと既存クラスや自作クラスを拡張することができます。<br />
会社や個人のプロジェクトでいつも使っている便利な拡張コードをまとめてみます。</p>
<h1>便利な Extension の紹介</h1>
<h2>クラス名の取得</h2>
<p>そのクラス・<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>のクラス名を取得するextensionです。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">extension</span> <span class="synIdentifier">NSObject</span> {
<span class="synPreProc">class</span> <span class="synIdentifier">var</span> className<span class="synSpecial">:</span> <span class="synType">String</span> {
<span class="synStatement">get</span> {
<span class="synStatement">return</span> NSStringFromClass(<span class="synIdentifier">self</span>).componentsSeparatedByString(<span class="synConstant">"."</span>).last<span class="synIdentifier">!</span>
}
}
<span class="synPreProc">var</span> <span class="synIdentifier">className</span><span class="synSpecial">:</span> <span class="synType">String</span> {
<span class="synStatement">get</span> {
<span class="synStatement">return</span> <span class="synIdentifier">self</span>.dynamicType.className
}
}
}
</pre>
<p>以下のような感じで使います。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink>MyCustomClass.className <span class="synComment">// "MyCustomClass"</span>
<span class="synPreProc">let</span> <span class="synIdentifier">myCell</span> <span class="synIdentifier">=</span> MyCustomClass()
print(myCell.className) <span class="synComment">// "MyCustomClass"</span>
</pre>
<h2>TableViewCell の登録と利用</h2>
<p>自作クラスを UITableView で扱う場合、</p>
<ul>
<li>あらかじめ <code>registerNib</code> や <code>registerClass</code> で登録し、</li>
<li><code>dequeueReusableCellWithIdentifier</code> して利用する</li>
</ul>
<p>ことが多いですが、それを簡潔に書けるようにする拡張です。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">extension</span> <span class="synIdentifier">UITableView</span> {
<span class="synPreProc">func</span> <span class="synIdentifier">registerCell</span><span class="synSpecial"><</span><span class="synIdentifier">T</span><span class="synSpecial">: </span><span class="synType">UITableViewCell</span><span class="synSpecial">></span>(type<span class="synSpecial">:</span> <span class="synType">T.Type</span>) {
<span class="synPreProc">let</span> <span class="synIdentifier">className</span> <span class="synIdentifier">=</span> type.className
<span class="synPreProc">let</span> <span class="synIdentifier">nib</span> <span class="synIdentifier">=</span> UINib(nibName<span class="synSpecial">:</span> <span class="synType">className</span>, bundle<span class="synSpecial">:</span> <span class="synType">nil</span>)
registerNib(nib, forCellReuseIdentifier<span class="synSpecial">:</span> <span class="synType">className</span>)
}
<span class="synPreProc">func</span> <span class="synIdentifier">dequeueCell</span><span class="synSpecial"><</span><span class="synIdentifier">T</span><span class="synSpecial">: </span><span class="synType">UITableViewCell</span><span class="synSpecial">></span>(type<span class="synSpecial">:</span> <span class="synType">T.Type</span>, indexPath<span class="synSpecial">:</span> <span class="synType">NSIndexPath</span>) <span class="synSpecial">-></span> <span class="synType">T</span> {
<span class="synStatement">return</span> <span class="synIdentifier">self</span>.dequeueReusableCellWithIdentifier(type.className, forIndexPath<span class="synSpecial">:</span> <span class="synType">indexPath</span>) <span class="synStatement">as!</span> <span class="synType">T</span>
}
}
</pre>
<p>自分は<strong>「カスタムのCellを扱う場合、ReuseIdentifier はそのカスタムCellのクラス名にする」</strong>というルールで統一していて、それに準じたコードとなっています。</p>
<p>以下のように使います。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink>tableView.registerCell(MyCustomCell.<span class="synIdentifier">self</span>) <span class="synComment">// 登録</span>
<span class="synPreProc">let</span> <span class="synIdentifier">cell</span> <span class="synIdentifier">=</span> tableView.dequeueCell(MyCustomCell.<span class="synIdentifier">self</span>) <span class="synComment">// 利用</span>
</pre>
<h2>CollectionView の登録と利用を簡単に</h2>
<p>上述したものの CollectionView 版です。<br />
UICollectionViewCell に加えて、ReusableView についても定義しています。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">extension</span> <span class="synIdentifier">UICollectionView</span> {
<span class="synPreProc">func</span> <span class="synIdentifier">registerCell</span><span class="synSpecial"><</span><span class="synIdentifier">T</span><span class="synSpecial">: </span><span class="synType">UICollectionViewCell</span><span class="synSpecial">></span>(type<span class="synSpecial">:</span> <span class="synType">T.Type</span>) {
<span class="synPreProc">let</span> <span class="synIdentifier">className</span> <span class="synIdentifier">=</span> type.className
<span class="synPreProc">let</span> <span class="synIdentifier">nib</span> <span class="synIdentifier">=</span> UINib(nibName<span class="synSpecial">:</span> <span class="synType">type.className</span>, bundle<span class="synSpecial">:</span> <span class="synType">nil</span>)
registerNib(nib, forCellWithReuseIdentifier<span class="synSpecial">:</span> <span class="synType">className</span>)
}
<span class="synPreProc">func</span> <span class="synIdentifier">registerReusableView</span><span class="synSpecial"><</span><span class="synIdentifier">T</span><span class="synSpecial">: </span><span class="synType">UICollectionReusableView</span><span class="synSpecial">></span>(type<span class="synSpecial">:</span> <span class="synType">T.Type</span>, kind<span class="synSpecial">:</span> <span class="synType">String</span>) {
<span class="synPreProc">let</span> <span class="synIdentifier">className</span> <span class="synIdentifier">=</span> type.className
<span class="synPreProc">let</span> <span class="synIdentifier">nib</span> <span class="synIdentifier">=</span> UINib(nibName<span class="synSpecial">:</span> <span class="synType">className</span>, bundle<span class="synSpecial">:</span> <span class="synType">nil</span>)
registerNib(nib, forSupplementaryViewOfKind<span class="synSpecial">:</span> <span class="synType">kind</span>, withReuseIdentifier<span class="synSpecial">:</span> <span class="synType">className</span>)
}
<span class="synPreProc">func</span> <span class="synIdentifier">dequeueCell</span><span class="synSpecial"><</span><span class="synIdentifier">T</span><span class="synSpecial">: </span><span class="synType">UICollectionViewCell</span><span class="synSpecial">></span>(type<span class="synSpecial">:</span> <span class="synType">T.Type</span>, forIndexPath indexPath<span class="synSpecial">:</span> <span class="synType">NSIndexPath</span>) <span class="synSpecial">-></span> <span class="synType">T</span> {
<span class="synStatement">return</span> dequeueReusableCellWithReuseIdentifier(type.className, forIndexPath<span class="synSpecial">:</span> <span class="synType">indexPath</span>) <span class="synStatement">as!</span> <span class="synType">T</span>
}
<span class="synPreProc">func</span> <span class="synIdentifier">dequeueReusableView</span><span class="synSpecial"><</span><span class="synIdentifier">T</span><span class="synSpecial">: </span><span class="synType">UICollectionReusableView</span><span class="synSpecial">></span>(kind<span class="synSpecial">:</span> <span class="synType">String</span>, type<span class="synSpecial">:</span> <span class="synType">T.Type</span>, indexPath<span class="synSpecial">:</span> <span class="synType">NSIndexPath</span>) <span class="synSpecial">-></span> <span class="synType">T</span> {
<span class="synStatement">return</span> dequeueReusableSupplementaryViewOfKind(kind,
withReuseIdentifier<span class="synSpecial">:</span> <span class="synType">type.className</span>,
forIndexPath<span class="synSpecial">:</span> <span class="synType">indexPath</span>) <span class="synStatement">as!</span> <span class="synType">T</span>
}
}
</pre>
<p>使い方は以下の通り。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synComment">// Cell</span>
collectionView.registerCell(MyCustomCollectionViewCell.<span class="synIdentifier">self</span>)
<span class="synPreProc">let</span> <span class="synIdentifier">cell</span> <span class="synIdentifier">=</span> collectionView.dequeueCell(MyCustomCollectionViewCell.<span class="synIdentifier">self</span>)
<span class="synComment">// ReusableView</span>
collectionView.registerReusableView(MyCustomReusableView.<span class="synIdentifier">self</span>, kind<span class="synSpecial">:</span> <span class="synType">UICollectionElementKindSectionHeader</span> )
<span class="synPreProc">let</span> <span class="synIdentifier">view</span> <span class="synIdentifier">=</span> collectionView.dequeueReusableView(UICollectionElementKindSectionHeader, type<span class="synSpecial">:</span> <span class="synType">MyCustomReusableView.self</span>, indexPath<span class="synSpecial">:</span> <span class="synType">indexPath</span>)
</pre>
<h2>UIColor を使いやすく</h2>
<p>Hexで色を指定したり、アプリでよく使うkeyColorを登録してます。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">extension</span> <span class="synIdentifier">UIColor</span> {
<span class="synPreProc">class</span> <span class="synIdentifier">func</span> color(hex<span class="synSpecial">:</span> <span class="synType">Int</span>, alpha<span class="synSpecial">:</span> <span class="synType">Double</span> <span class="synIdentifier">=</span> <span class="synConstant">1.0</span>) <span class="synSpecial">-></span> <span class="synType">UIColor</span> {
<span class="synPreProc">let</span> <span class="synIdentifier">red</span> <span class="synIdentifier">=</span> Double((hex <span class="synIdentifier">&</span> <span class="synConstant">0xFF0000</span>) <span class="synIdentifier">>></span> <span class="synConstant">16</span>) <span class="synIdentifier">/</span> <span class="synConstant">255.0</span>
<span class="synPreProc">let</span> <span class="synIdentifier">green</span> <span class="synIdentifier">=</span> Double((hex <span class="synIdentifier">&</span> <span class="synConstant">0xFF00</span>) <span class="synIdentifier">>></span> <span class="synConstant">8</span>) <span class="synIdentifier">/</span> <span class="synConstant">255.0</span>
<span class="synPreProc">let</span> <span class="synIdentifier">blue</span> <span class="synIdentifier">=</span> Double((hex <span class="synIdentifier">&</span> <span class="synConstant">0xFF</span>)) <span class="synIdentifier">/</span> <span class="synConstant">255.0</span>
<span class="synStatement">return</span> UIColor(red<span class="synSpecial">:</span> <span class="synType">CGFloat</span>(red), green<span class="synSpecial">:</span> <span class="synType">CGFloat</span>(green), blue<span class="synSpecial">:</span> <span class="synType">CGFloat</span>(blue), alpha<span class="synSpecial">:</span> <span class="synType">CGFloat</span>(alpha))
}
<span class="synPreProc">class</span> <span class="synIdentifier">func</span> defaultColor(alpha<span class="synSpecial">:</span> <span class="synType">Double</span> <span class="synIdentifier">=</span> <span class="synConstant">1.0</span>) <span class="synSpecial">-></span> <span class="synType">UIColor</span> {
<span class="synStatement">return</span> UIColor.color(<span class="synConstant">0x00ACED</span>, alpha<span class="synSpecial">:</span> <span class="synType">alpha</span>)
}
}
</pre>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synComment">// 使い方</span>
<span class="synPreProc">let</span> <span class="synIdentifier">color</span> <span class="synIdentifier">=</span> UIColor.color(<span class="synConstant">0xCCCCCC</span>)
<span class="synPreProc">let</span> <span class="synIdentifier">defaultColor</span> <span class="synIdentifier">=</span> UIColor.defaultColor()
</pre>
<h2>現在表示中の ViewController を探す</h2>
<p>presentedViewController をできるだけ探索し、表示中の ViewController を返します。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">extension</span> <span class="synIdentifier">UIApplication</span> {
<span class="synPreProc">func</span> <span class="synIdentifier">topViewController</span>() <span class="synSpecial">-></span> <span class="synType">UIViewController?</span> {
<span class="synStatement">if</span> <span class="synPreProc">var</span> <span class="synIdentifier">topViewController</span> <span class="synIdentifier">=</span> UIApplication.sharedApplication().keyWindow?.rootViewController {
<span class="synStatement">while</span> (topViewController.presentedViewController <span class="synIdentifier">!=</span> <span class="synConstant">nil</span>) {
topViewController <span class="synIdentifier">=</span> topViewController.presentedViewController<span class="synIdentifier">!</span>
}
<span class="synStatement">return</span> topViewController
} <span class="synStatement">else</span> {
<span class="synStatement">return</span> <span class="synConstant">nil</span>
}
}
}
</pre>
<p>UIAlertController と組み合わせて、以下のように使っています。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">let</span> <span class="synIdentifier">alertController</span> <span class="synIdentifier">=</span> UIAlertController(title<span class="synSpecial">:</span> <span class="synConstant">"成功!"</span>,
message<span class="synSpecial">:</span> <span class="synConstant">"正常に削除できました"</span>,
preferredStyle<span class="synSpecial">:</span> .Alert)
alertController.addAction(UIAlertAction(
title<span class="synSpecial">:</span> <span class="synConstant">"OK"</span>,
style<span class="synSpecial">:</span> .Cancel,
handler<span class="synSpecial">:</span> <span class="synType">nil</span>))
UIApplication.sharedApplication().topViewController()?
.presentViewController(alertController, animated<span class="synSpecial">:</span> <span class="synType">true</span>, completion<span class="synSpecial">:</span> <span class="synType">nil</span>)
</pre>
<p>UIAlertController は必ず ViewController から <code>presentViewController</code> で呼ぶ必要があるため、topViewController() で取得できるようにしておくと昔のUIAlertViewのように使えて便利ですね。</p>
<p>ちなみに UIAlertView / UIActionSheet は <a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8 から deprecated となっています。</p>
<h2>NSUserDefaults で管理する値を拡張で</h2>
<p>「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>が完了したか」「初回起動のユーザーか」などの管理に NSUserDefaults を使っていますが、そのフラグを extension のプロパティとして定義してます。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synStatement">private</span> <span class="synPreProc">let</span> <span class="synIdentifier">isFirstSessionDoneKey</span> <span class="synIdentifier">=</span> <span class="synConstant">"IS_FIRST_SESSION_DONE"</span>
<span class="synPreProc">extension</span> <span class="synIdentifier">NSUserDefaults</span> {
<span class="synPreProc">var</span> <span class="synIdentifier">isFirstSessionDone</span><span class="synSpecial">:</span> <span class="synType">Bool?</span> {
<span class="synStatement">get</span> {
<span class="synStatement">return</span> <span class="synIdentifier">self</span>.objectForKey(isFirstSessionDoneKey) <span class="synStatement">as?</span> <span class="synType">Bool</span>
}
<span class="synStatement">set</span> {
<span class="synIdentifier">self</span>.setObject(<span class="synConstant">true</span>, forKey<span class="synSpecial">:</span> <span class="synType">isFirstSessionDoneKey</span>)
<span class="synIdentifier">self</span>.synchronize()
}
}
}
</pre>
<p>フラグ系の処理がバラバラにならずまとめて書けるので気に入ってます。管理する数が増えてきたら専用のクラスを作った方が良いかと思います。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synComment">// 使い方</span>
NSUserDefaults.standardUserDefaults.isFirstSessionDone <span class="synIdentifier">=</span> <span class="synConstant">true</span>
</pre>
<h2>Storyboard からの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>作成</h2>
<p>開発時の規則として、</p>
<ul>
<li>基本的に1Storyboard - 1ViewController</li>
<li>Storyboardの名前と、initial な ViewController のクラス名を同じにする</li>
</ul>
<p>というルールがあり、その上で以下の初期化メソッドを定義しています。
(これは extension ではなく大域関数になります)</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">func</span> <span class="synIdentifier">instantiate</span><span class="synSpecial"><</span><span class="synIdentifier">T</span><span class="synSpecial">: </span><span class="synType">UIViewController</span><span class="synSpecial"> where </span><span class="synIdentifier">T</span><span class="synSpecial">: </span><span class="synType">NSObject</span><span class="synSpecial">></span>(_<span class="synSpecial">:</span> <span class="synType">T.Type</span>) <span class="synSpecial">-></span> <span class="synType">T</span> {
<span class="synPreProc">let</span> <span class="synIdentifier">storyboard</span> <span class="synIdentifier">=</span> UIStoryboard(name<span class="synSpecial">:</span> <span class="synType">T.className</span>, bundle<span class="synSpecial">:</span> <span class="synType">nil</span>)
<span class="synStatement">return</span> storyboard.instantiateInitialViewController() <span class="synStatement">as!</span> <span class="synType">T</span>
}
<span class="synPreProc">func</span> <span class="synIdentifier">instantiate</span><span class="synSpecial"><</span><span class="synIdentifier">T</span><span class="synSpecial">: </span><span class="synType">UIViewController</span><span class="synSpecial"> where </span><span class="synIdentifier">T</span><span class="synSpecial">: </span><span class="synType">NSObject</span><span class="synSpecial">></span>(_<span class="synSpecial">:</span> <span class="synType">T.Type</span>, storyboard<span class="synSpecial">:</span> <span class="synType">String</span>) <span class="synSpecial">-></span> <span class="synType">T</span> {
<span class="synPreProc">let</span> <span class="synIdentifier">storyboard</span> <span class="synIdentifier">=</span> UIStoryboard(name<span class="synSpecial">:</span> <span class="synType">storyboard</span>, bundle<span class="synSpecial">:</span> <span class="synType">nil</span>)
<span class="synStatement">return</span> storyboard.instantiateViewControllerWithIdentifier(T.className) <span class="synStatement">as!</span> <span class="synType">T</span>
}
</pre>
<p>使い方は以下の通り:</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synComment">// initial な ViewController を取得</span>
<span class="synPreProc">let</span> <span class="synIdentifier">topVC</span> <span class="synIdentifier">=</span> instantiate(TopViewController.<span class="synIdentifier">self</span>)
<span class="synComment">// initial でない ViewController を取得</span>
<span class="synComment">// (1Storyboard - 1ViewController でない特別な場合でのみ利用)</span>
<span class="synPreProc">let</span> <span class="synIdentifier">topDetailVC</span> <span class="synIdentifier">=</span> instantiate(TopDetailViewController.<span class="synIdentifier">self</span>, storyboard<span class="synSpecial">:</span> <span class="synConstant">"TopViewController"</span>)
</pre>
<p>詳細については以下のQiitaが詳しいです。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fqiita.com%2FYusukeHosonuma%2Fitems%2F53e126da3e4000d1683a" title="UIViewControllerに、同名のStoryboardから生成する能力を与える - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://qiita.com/YusukeHosonuma/items/53e126da3e4000d1683a">qiita.com</a></cite></p>
<h2>Nib からの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>作成</h2>
<p>カスタムのUIViewなどを扱う場合の記述です。<br />
Storyboard と同じく、「MyCustomView」というクラス名の場合は「MyCustomView.xib」というファイル名にする規則を設けています。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">func</span> <span class="synIdentifier">instantiateFromNib</span><span class="synSpecial"><</span><span class="synIdentifier">T</span><span class="synSpecial">: </span><span class="synType">UIView</span><span class="synSpecial">, </span><span class="synIdentifier">U</span><span class="synSpecial">: </span><span class="synType">AnyObject</span><span class="synSpecial"> where </span><span class="synIdentifier">T</span><span class="synSpecial">: </span><span class="synType">NSObject</span><span class="synSpecial">></span>(_<span class="synSpecial">:</span> <span class="synType">T.Type</span>, owner<span class="synSpecial">:</span> <span class="synType">U</span>) <span class="synSpecial">-></span> <span class="synType">T</span> {
<span class="synStatement">return</span> UINib(nibName<span class="synSpecial">:</span> <span class="synType">T.className</span>, bundle<span class="synSpecial">:</span> <span class="synType">nil</span>).instantiateWithOwner(owner, options<span class="synSpecial">:</span> <span class="synType">nil</span>)[<span class="synConstant">0</span>] <span class="synStatement">as!</span> <span class="synType">T</span>
}
</pre>
<p>使い方は以下の通りです。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">let</span> <span class="synIdentifier">myCustomView</span> <span class="synIdentifier">=</span> instantiateFromNib(MyCustomView.<span class="synIdentifier">self</span>, owner<span class="synSpecial">:</span> <span class="synType">self</span>)
</pre>
<h2>追記: namespaceの衝突について</h2>
<p>既存クラスを extension で拡張する場合、メソッド名の衝突を気にする必要があります。<br />
自分のいまの環境だと小規模&1人プロジェクトが多いためそのまま使ってますが、規模が大きくなったら Embedded Framework で細かく分けようかと考えていました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.toyship.org%2Farchives%2F2099" title="Swift の Embedded Framework と namespace - Toyship.org" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://www.toyship.org/archives/2099">www.toyship.org</a></cite></p>
<p>ただ、誤って同名で変数やメソッドを定義してしまった場合には<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>エラーを吐いてくれてそこで気づけるので、そこまで気にしなくても良いのかもしれません。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20151102/20151102091512.png" alt="f:id:himaratsu:20151102091512p:plain" width="1024" height="81" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h1>まとめ</h1>
<p>自分がいつも使う extension を紹介しました。
よく使う処理を簡潔に書けるほか、Storyboard の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CC%BF%CC%BE%B5%AC%C2%A7">命名規則</a>や初期化の方法など、extension そのものがコーディング規約となる側面もあり、非常に有用だと感じています。</p>
<p>紹介したすべてのコードは以下のGistからお使いいただけます。</p>
<ul>
<li><a href="https://gist.github.com/himaratsu/a7e35241dba0b11be0f8">https://gist.github.com/himaratsu/a7e35241dba0b11be0f8</a></li>
</ul>
<p>ほかにも便利な extension があるぞ、という方はぜひ教えてください :)</p>
<h1>参考資料</h1>
<ul>
<li><a href="https://speakerdeck.com/yuseinishiyama/making-your-app-static">Making Your App Static - Speaker Deck</a></li>
</ul>
<h1>おすすめ書籍</h1>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B01701BLDQ?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51fwe-vI2GL._SL500_.jpg" class="hatena-asin-detail-image" alt="Swiftデザインパターン" title="Swiftデザインパターン"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B01701BLDQ?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">Swiftデザインパターン</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C0%A5%E0%A1%A6%A5%D5%A5%EA%A1%BC%A5%DE%A5%F3" class="keyword">アダム・フリーマン</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%E6%C6%B1%CB%BC%D2">翔泳社</a></li></ul><a href="https://www.amazon.co.jp/dp/B01701BLDQ?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>基礎から上級へのレベルアップに。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4798043656?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51AyAHn4B2L._SL500_.jpg" class="hatena-asin-detail-image" alt="TECHNICAL MASTERはじめてのiOSアプリ開発Swift対応版" title="TECHNICAL MASTERはじめてのiOSアプリ開発Swift対応版"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4798043656?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">TECHNICAL MASTERはじめてのiOSアプリ開発Swift対応版</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C4%B9%C3%AB%C0%EE%20%C3%D2%B4%F5" class="keyword">長谷川 智希</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%A8%CF%C2%A5%B7%A5%B9%A5%C6%A5%E0">秀和システム</a></li></ul><a href="https://www.amazon.co.jp/dp/4798043656?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>ステップごとに丁寧でわかりやすく、入門の方におすすめです。</p>
<h1>関連記事</h1>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fhealth%2Fchiropractic" title="健康にコードを書き続けるために骨に気をつける - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/health/chiropractic">himaratsu.hatenablog.com</a></cite></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Ffriendcolor" title="iOSアプリ開発で上手に色を操るための設定まとめ - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/friendcolor">himaratsu.hatenablog.com</a></cite></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fswift%2Fbooks" title="年末年始に読みたいSwift勉強のためのおすすめ本・書籍やサイトなど(追記あり) - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/swift/books">himaratsu.hatenablog.com</a></cite></p>
himaratsu
UITableView の編集モードを利用してデータの削除や並び替えを行う
hatenablog://entry/6653458415120171614
2015-09-05T01:46:22+09:00
2022-02-24T20:51:03+09:00 iOS アプリ開発によく登場する UITableView には編集モードというのがあります。 データの並び替えや削除に便利なためよく使うのですが、毎回使い方を調べてる気がするので記事にまとめてみます。
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>によく登場する UITableView には編集モードというのがあります。<br />
データの並び替えや削除に便利なためよく使うのですが、毎回使い方を調べてる気がするので記事にまとめてみます。</p>
<h1>編集ができる UITableView をつくる</h1>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150905/20150905014754.png" alt="f:id:himaratsu20150725222016p:plain" title="完成イメージ" class="hatena-fotolife" itemprop="image" style="width:300px;border:1px solid #cccccc"></p>
<p>こんな感じの単純なテーブルビューを例にします。</p>
<p>このデー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%BB%A5%C3%A5%C8">タセット</a>は以下のように変数で保持していて、削除や並び替えが発生したら変数のデータも合わせて変更します。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">var</span> <span class="synIdentifier">titles</span> <span class="synIdentifier">=</span> [<span class="synConstant">"0: Hello"</span>, <span class="synConstant">"1: World"</span>, <span class="synConstant">"2: Swift"</span>, <span class="synConstant">"3: Programming"</span>]
</pre>
<h2>編集モードに切り替えられるようにする</h2>
<h3>編集ボタンの配置</h3>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150905/20150905011220.png" alt="f:id:himaratsu20150725222016p:plain" title="完成イメージ" class="hatena-fotolife" itemprop="image" style="width:80px; border:1px solid #cccccc"></p>
<p>↑のような編集ボタンは予め用意されており、以下のように使用できます。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synStatement">override</span> <span class="synPreProc">func</span> <span class="synIdentifier">viewDidLoad</span>() {
<span class="synIdentifier">super</span>.viewDidLoad()
<span class="synComment">// 編集ボタンを左上に配置</span>
navigationItem.leftBarButtonItem <span class="synIdentifier">=</span> editButtonItem()
}
</pre>
<p>このボタンは押すたびに Edit → Done → Edit → ... と切り替わります。<br />
(日本語環境では「編集」「完了」という名前に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%ED%A1%BC%A5%AB%A5%E9%A5%A4%A5%BA">ローカライズ</a>されている)</p>
<h3>編集ボタンを押した時の処理</h3>
<p>Edit ボタンが押されると、<code>setEditing(_)</code> が呼ばれます。<br />
このタイミングで UITableView を編集モードにしたいので、 tableView の editing プロパティを使って変更します。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synStatement">override</span> <span class="synPreProc">func</span> <span class="synIdentifier">setEditing</span>(editing<span class="synSpecial">:</span> <span class="synType">Bool</span>, animated<span class="synSpecial">:</span> <span class="synType">Bool</span>) {
<span class="synIdentifier">super</span>.setEditing(editing, animated<span class="synSpecial">:</span> <span class="synType">animated</span>)
tableView.editing <span class="synIdentifier">=</span> editing
}
</pre>
<h2>データを削除する</h2>
<h3>削除可能なセルの indexPath を指定</h3>
<p>今回はすべての Cell を削除可能としています。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">func</span> <span class="synIdentifier">tableView</span>(tableView<span class="synSpecial">:</span> <span class="synType">UITableView</span>, canEditRowAtIndexPath indexPath<span class="synSpecial">:</span> <span class="synType">NSIndexPath</span>) <span class="synSpecial">-></span> <span class="synType">Bool</span> {
<span class="synStatement">return</span> <span class="synConstant">true</span>
}
</pre>
<h3>実際に削除された時の処理を実装する</h3>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">func</span> <span class="synIdentifier">tableView</span>(tableView<span class="synSpecial">:</span> <span class="synType">UITableView</span>, commitEditingStyle editingStyle<span class="synSpecial">:</span> <span class="synType">UITableViewCellEditingStyle</span>, forRowAtIndexPath indexPath<span class="synSpecial">:</span> <span class="synType">NSIndexPath</span>) {
<span class="synComment">// 先にデータを更新する</span>
titles.removeAtIndex(indexPath.row)
<span class="synComment">// それからテーブルの更新</span>
tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow<span class="synSpecial">:</span> <span class="synType">indexPath.row</span>, inSection<span class="synSpecial">:</span> <span class="synConstant">0</span>)],
withRowAnimation<span class="synSpecial">:</span> <span class="synType">UITableViewRowAnimation.Fade</span>)
}
</pre>
<p>ここで、「データの編集」→「テーブルの更新」という順番で処理するのが重要です。
この順番を間違えると以下のようなエラーが出て落ちてしまいます。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink>reason<span class="synSpecial">:</span> 'Invalid update<span class="synSpecial">:</span> <span class="synType">invalid</span> number of rows <span class="synStatement">in</span> section <span class="synConstant">0</span>. The number of rows contained <span class="synStatement">in</span> an existing section after the update (<span class="synConstant">4</span>) must be equal to the number of rows contained <span class="synStatement">in</span> that section before the update (<span class="synConstant">4</span>), plus or minus the number of rows inserted or deleted from that section (<span class="synConstant">0</span> inserted, <span class="synConstant">1</span> deleted) and plus or minus the number of rows moved into or out of that section (<span class="synConstant">0</span> moved <span class="synStatement">in</span>, <span class="synConstant">0</span> moved out).'
</pre>
<h2>データを並び替える</h2>
<h3>並び替え可能なセルの indexPath を指定</h3>
<p>今回はすべての Cell を並び替え可能とします。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">func</span> <span class="synIdentifier">tableView</span>(tableView<span class="synSpecial">:</span> <span class="synType">UITableView</span>, canMoveRowAtIndexPath indexPath<span class="synSpecial">:</span> <span class="synType">NSIndexPath</span>) <span class="synSpecial">-></span> <span class="synType">Bool</span> {
<span class="synStatement">return</span> <span class="synConstant">true</span>
}
</pre>
<h3>並び替え完了後の処理を実装する</h3>
<p>ユーザーが並び替えて指を離したタイミングで以下の <a class="keyword" href="http://d.hatena.ne.jp/keyword/delegate">delegate</a> が呼ばれます。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">func</span> <span class="synIdentifier">tableView</span>(tableView<span class="synSpecial">:</span> <span class="synType">UITableView</span>, moveRowAtIndexPath sourceIndexPath<span class="synSpecial">:</span> <span class="synType">NSIndexPath</span>, toIndexPath destinationIndexPath<span class="synSpecial">:</span> <span class="synType">NSIndexPath</span>) {
<span class="synPreProc">let</span> <span class="synIdentifier">targetTitle</span> <span class="synIdentifier">=</span> titles[sourceIndexPath.row]
<span class="synStatement">if</span> <span class="synPreProc">let</span> <span class="synIdentifier">index</span> <span class="synIdentifier">=</span> titles.indexOf(targetTitle) {
titles.removeAtIndex(index)
titles.insert(targetTitle, atIndex<span class="synSpecial">:</span> <span class="synType">destinationIndexPath.row</span>)
}
}
</pre>
<p><code>sourceIndexPath</code> にそのデータの元の位置が、<code>destinationIndexPath</code> に移動先の位置が入ってますので、その情報を元に並び替えを行います。</p>
<h2>その他のTips</h2>
<h3>通常モードではスワイプ削除できないようにする</h3>
<p><code>canEditRowAtIndexPath</code> で指定したセルは、編集モード以外に、セルを左方向へスワイプすることでも削除できます。</p>
<p>しかし、最近流行りの <a class="keyword" href="http://d.hatena.ne.jp/keyword/SmartNews">SmartNews</a> のようなタブUI(上にタブが並んだUI)では、横方向のスワイプがバッティングしてしまうため<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B6%A5%D3%A5%EA%A5%C6%A5%A3">ユーザビリティ</a>がよろしくありません。</p>
<p>普段はスワイプ削除はさせず、「Edit」ボタンを押されて編集モードになった時のみ削除を可能にするためには、以下のように記述します。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">func</span> <span class="synIdentifier">tableView</span>(tableView<span class="synSpecial">:</span> <span class="synType">UITableView</span>, editingStyleForRowAtIndexPath indexPath<span class="synSpecial">:</span> <span class="synType">NSIndexPath</span>) <span class="synSpecial">-></span> <span class="synType">UITableViewCellEditingStyle</span> {
<span class="synStatement">if</span> tableView.editing {
<span class="synStatement">return</span> UITableViewCellEditingStyle.Delete
} <span class="synStatement">else</span> {
<span class="synStatement">return</span> UITableViewCellEditingStyle.None
}
}
</pre>
<h3>編集モード中もセルをタップできるようにする</h3>
<p>デフォルトでは編集モード中はセルを選択できません。<br />
選択できるようにするには、以下のように記述します。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink>tableView.allowsSelectionDuringEditing <span class="synIdentifier">=</span> <span class="synConstant">true</span>
</pre>
<p>あるいは、 Storyboard 上の下図の項目からも指定できます。</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150905/20150905013114.png" alt="f:id:himaratsu20150725222016p:plain" title="完成イメージ" class="hatena-fotolife" itemprop="image" style="width:600px;border:1px solid #cccccc"></p>
<h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a></h1>
<p>今回使用したサンプルコードは以下にまとめています。</p>
<ul>
<li><a href="https://github.com/himaratsu/TableViewEditSample">GitHub - himaratsu/TableViewEditSample</a></li>
</ul>
<h1>まとめ</h1>
<p>簡単に削除や並び替えの UI を作れる UITableView の編集モードについて書きました。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> に昔からある機能なのでユーザーの馴染みも深く、使いやすくて良いと思います。</p>
<h2>関連記事</h2>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fswift%2Ftiqav" title="SwiftでTiqav APIを叩くビューワアプリを100行でつくったよ - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/swift/tiqav">himaratsu.hatenablog.com</a></cite></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fobjc%2Fsmartnews" title="SmartNews風のレイアウトをInterface Builderを使ってつくる - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/objc/smartnews">himaratsu.hatenablog.com</a></cite></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fios%2Fcustomview" title="カスタムViewをNibから初期化し、IBDesignableとIBInspectableで便利に使う - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://himaratsu.hatenablog.com/entry/ios/customview">himaratsu.hatenablog.com</a></cite></p>
<h2>おすすめ書籍</h2>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4798043656?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51AyAHn4B2L._SL500_.jpg" class="hatena-asin-detail-image" alt="TECHNICAL MASTERはじめてのiOSアプリ開発Swift対応版" title="TECHNICAL MASTERはじめてのiOSアプリ開発Swift対応版"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4798043656?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">TECHNICAL MASTERはじめてのiOSアプリ開発Swift対応版</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C4%B9%C3%AB%C0%EE%20%C3%D2%B4%F5" class="keyword">長谷川 智希</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%A8%CF%C2%A5%B7%A5%B9%A5%C6%A5%E0">秀和システム</a></li></ul><a href="https://www.amazon.co.jp/dp/4798043656?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/477415654X?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51nXP3TKXVL._SL500_.jpg" class="hatena-asin-detail-image" alt="コーディングを支える技術 ~成り立ちから学ぶプログラミング作法 (WEB+DB PRESS plus)" title="コーディングを支える技術 ~成り立ちから学ぶプログラミング作法 (WEB+DB PRESS plus)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/477415654X?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">コーディングを支える技術 ~成り立ちから学ぶプログラミング作法 (WEB+DB PRESS plus)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C0%BE%C8%F8%20%C2%D9%CF%C2" class="keyword">西尾 泰和</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%BB%BD%D1%C9%BE%CF%C0%BC%D2">技術評論社</a></li></ul><a href="https://www.amazon.co.jp/dp/477415654X?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B00JNTZ89W/samura1-22/">[asin:B00JNTZ89W:detail]</a></p>
himaratsu
カスタムViewをNibから初期化し、IBDesignableとIBInspectableで便利に使う
hatenablog://entry/8454420450103147681
2015-07-26T12:20:27+09:00
2022-02-24T19:50:57+09:00 iOS開発をしていると、独自のViewを作りたい場合があります。 実現する方法は色々あると思うのですが、最近自分がやっている方法をまとめます。
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>開発をしていると、独自のViewを作りたい場合があります。<br />
実現する方法は色々あると思うのですが、最近自分がやっている方法をまとめます。</p>
<p>(以下で実装しているコードは <a href="https://github.com/himaratsu/CustomViewSample">GitHub</a> にすべてあげています)</p>
<h1>目指すゴール</h1>
<ul>
<li>Storyboard / Interface Buidler から初期化できる</li>
<li>コードからも初期化できる</li>
<li>IBDesignable & IBInspectable に対応している</li>
<li>各画面から使いやすい(汎用性が高い)</li>
</ul>
<p>上記を満たすカスタムViewを目指します。</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150725/20150725222016.png" alt="f:id:himaratsu20150725222016p:plain" title="完成イメージ" class="hatena-fotolife" itemprop="image" style="width:300px"></p>
<p>こんな感じの、ユーザーにレビューをお願いするViewで、<br />
↓みたいにStoryboard上から値をセットできるものを作ってみます。</p>
<p><a href="http://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150726/20150726001213.gif" class="http-image"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150726/20150726001213.gif" class="http-image" alt="http://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150726/20150726001213.gif"></a></p>
<h1>実装の流れ</h1>
<h2>1. カスタムViewのxibとクラスを用意する</h2>
<h5>(1) xibを作成</h5>
<p>MyCustomView.xib というファイルを作成します。<br />
Size を "Freeform" にして適当にリサイズし、Status Bar を "None" にします。</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150725/20150725234453.png" alt="xibをつくってリサイズする" title="xibをつくってリサイズする" class="hatena-fotolife" itemprop="image" style="width:600px; border:1px solid #ccc"></p>
<h5>(2) <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>の配置とレイアウト</h5>
<p>上から UILabel, UIImageView, UIButton を追加して AutoLayout をセットします。</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150725/20150725222016.png" alt="f:id:himaratsu20150725222016p:plain" title="完成イメージ" class="hatena-fotolife" itemprop="image" style="width:350px"></p>
<h5>(3) クラスの作成</h5>
<p>MyCustomView クラスを UIView のサブクラスとして作成します。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">class</span> <span class="synIdentifier">MyCustomView</span><span class="synSpecial">:</span> <span class="synType">UIView</span> { <span class="synIdentifier">...</span> }
</pre>
<h2>2. xibとクラスを紐づける</h2>
<p>xib を 開き、<strong>File's Owner</strong> にカスタムViewのクラス名を入力します。</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150725/20150725234254.png" alt="xibとクラスを紐づける" title="xibとクラスを紐づける" class="hatena-fotolife" itemprop="image" style="width:600px"></p>
<p>View とではなく、File's Owner と紐づけます。</p>
<h2>3. 初期化のコードを書く</h2>
<p>以下のように初期化の実装を記述します。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">class</span> <span class="synIdentifier">MyCustomView</span><span class="synSpecial">:</span> <span class="synType">UIView</span> {
<span class="synComment">// コードから初期化はここから</span>
<span class="synStatement">override</span> <span class="synIdentifier">init</span>(frame<span class="synSpecial">:</span> <span class="synType">CGRect</span>) {
<span class="synIdentifier">super</span>.<span class="synIdentifier">init</span>(frame<span class="synSpecial">:</span> <span class="synType">frame</span>)
comminInit()
}
<span class="synComment">// Storyboard/xib から初期化はここから</span>
<span class="synStatement">required</span> <span class="synIdentifier">init</span>?(coder aDecoder<span class="synSpecial">:</span> <span class="synType">NSCoder</span>) {
<span class="synIdentifier">super</span>.<span class="synIdentifier">init</span>(coder<span class="synSpecial">:</span> <span class="synType">aDecoder</span>)
comminInit()
}
<span class="synComment">// xibからカスタムViewを読み込んで準備する</span>
<span class="synStatement">private</span> <span class="synPreProc">func</span> <span class="synIdentifier">comminInit</span>() {
<span class="synComment">// MyCustomView.xib からカスタムViewをロードする</span>
<span class="synPreProc">let</span> <span class="synIdentifier">bundle</span> <span class="synIdentifier">=</span> NSBundle(forClass<span class="synSpecial">:</span> <span class="synType">self.dynamicType</span>)
<span class="synPreProc">let</span> <span class="synIdentifier">nib</span> <span class="synIdentifier">=</span> UINib(nibName<span class="synSpecial">:</span> <span class="synConstant">"MyCustomView"</span>, bundle<span class="synSpecial">:</span> <span class="synType">bundle</span>)
<span class="synPreProc">let</span> <span class="synIdentifier">view</span> <span class="synIdentifier">=</span> nib.instantiateWithOwner(<span class="synIdentifier">self</span>, options<span class="synSpecial">:</span> <span class="synType">nil</span>).first <span class="synStatement">as!</span> <span class="synType">UIView</span>
addSubview(view)
<span class="synComment">// カスタムViewのサイズを自分自身と同じサイズにする</span>
view.translatesAutoresizingMaskIntoConstraints <span class="synIdentifier">=</span> <span class="synConstant">false</span>
<span class="synPreProc">let</span> <span class="synIdentifier">bindings</span> <span class="synIdentifier">=</span> [<span class="synConstant">"view"</span><span class="synSpecial">:</span> <span class="synType">view</span>]
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(<span class="synConstant">"H:|[view]|"</span>,
options<span class="synSpecial">:</span><span class="synType">NSLayoutFormatOptions</span>(rawValue<span class="synSpecial">:</span> <span class="synConstant">0</span>),
metrics<span class="synSpecial">:</span><span class="synType">nil</span>,
views<span class="synSpecial">:</span> <span class="synType">bindings</span>))
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(<span class="synConstant">"V:|[view]|"</span>,
options<span class="synSpecial">:</span><span class="synType">NSLayoutFormatOptions</span>(rawValue<span class="synSpecial">:</span> <span class="synConstant">0</span>),
metrics<span class="synSpecial">:</span><span class="synType">nil</span>,
views<span class="synSpecial">:</span> <span class="synType">bindings</span>))
}
</pre>
<p><code>init(frame: CGRect)</code> はコードから初期化する場合に呼ばれ、<br />
<code>init(coder aDecoder: NSCoder)</code> は Storyboard/xib からの初期化で呼ばれます。</p>
<p>ここでは初期化の処理を <code>commonInit()</code> メソッドに共<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%CC%B2%BD">通化</a>してどちらからも呼んでいるので、コードからでも Storyboard/xib からでも初期化して使うことができます。</p>
<h2>4. IBOutlet と IBAction を設定する</h2>
<p>xibからCtrl+ドラッグで、IBOutlet や IBAction を設定します。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synType">@IBOutlet</span> <span class="synType">weak</span> <span class="synStatement">private</span> <span class="synPreProc">var</span> <span class="synIdentifier">titleLabel</span><span class="synSpecial">:</span> <span class="synType">UILabel!</span>
<span class="synType">@IBOutlet</span> <span class="synType">weak</span> <span class="synStatement">private</span> <span class="synPreProc">var</span> <span class="synIdentifier">iconImageView</span><span class="synSpecial">:</span> <span class="synType">UIImageView!</span>
<span class="synType">@IBOutlet</span> <span class="synType">weak</span> <span class="synStatement">private</span> <span class="synPreProc">var</span> <span class="synIdentifier">okButton</span><span class="synSpecial">:</span> <span class="synType">UIButton!</span>
<span class="synComment">// 「ALPACAを応援する」ボタンが押された際の挙動</span>
<span class="synType">@IBAction</span> <span class="synType">func</span> okButtonTouched(sender<span class="synSpecial">:</span> <span class="synType">AnyObject</span>) {
<span class="synPreProc">let</span> <span class="synIdentifier">appStoreUrl</span> <span class="synIdentifier">=</span> <span class="synConstant">"https://itunes.apple.com/app/id934444072?mt=8"</span>
<span class="synStatement">if</span> <span class="synPreProc">let</span> <span class="synIdentifier">URL</span> <span class="synIdentifier">=</span> NSURL(string<span class="synSpecial">:</span> <span class="synType">appStoreUrl</span>) {
<span class="synStatement">if</span> UIApplication.sharedApplication().canOpenURL(URL) {
UIApplication.sharedApplication().openURL(URL)
}
}
}
</pre>
<p>ここまでで動作としては完成です。</p>
<h2>5. @IBDesignable を指定する</h2>
<p>すでに動くものはできていますが、さらに使いやすく工夫していきます。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> 6以降では、<strong>@IBDesignable</strong>を対象クラスに指定することで、Storyboard 上でカスタムViewの見た目を確認することができます。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synType">@IBDesignable</span>
<span class="synPreProc">class</span> <span class="synIdentifier">MyCustomView</span><span class="synSpecial">:</span> <span class="synType">UIView</span> {
<span class="synIdentifier">...</span>
</pre>
<p>上記のように記述すると、Storyboard上では以下の右のように表示されます。</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150726/20150726000910.png" alt="IBDesignable 有りと無し" title="IBDesignable 有りと無し" class="hatena-fotolife" itemprop="image" style="width:500px; border:1px solid #ccc"></p>
<p>便利ですね!</p>
<h2>6. @IBInspectable を設定する</h2>
<p>さらに便利に使うために、<strong>@IBInspectable</strong> を設定します。</p>
<p>これも @IBDesignable と同じく <a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> 6 から使えるようになったもので、設定するとカスタムクラスのプロパティの値をStoryboard上からセットできます。</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150725/20150725233338.png" alt="IBInspectableを指定するとここから値をセットできる" title="IBInspectableを指定するとここから値をセットできる" class="hatena-fotolife" itemprop="image" style="width:300px; border:1px solid #ccc"></p>
<p>上記のようにするためには、MyCustomView.swift に以下のように記述します。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synType">@IBDesignable</span>
<span class="synPreProc">class</span> <span class="synIdentifier">MyCustomView</span><span class="synSpecial">:</span> <span class="synType">UIView</span> {
<span class="synComment">// viewの枠線の色</span>
<span class="synType">@IBInspectable</span> <span class="synType">var</span> borderColor<span class="synSpecial">:</span> <span class="synType">UIColor</span> <span class="synIdentifier">=</span> UIColor.clearColor() {
<span class="synStatement">didSet</span> {
<span class="synIdentifier">self</span>.layer.borderColor <span class="synIdentifier">=</span> borderColor.CGColor
}
}
<span class="synComment">// viewの枠線の太さ</span>
<span class="synType">@IBInspectable</span> <span class="synType">var</span> borderWidth<span class="synSpecial">:</span> <span class="synType">CGFloat</span> <span class="synIdentifier">=</span> <span class="synConstant">0</span> {
<span class="synStatement">didSet</span> {
<span class="synIdentifier">self</span>.layer.borderWidth <span class="synIdentifier">=</span> borderWidth
}
}
<span class="synComment">// viewの角丸</span>
<span class="synType">@IBInspectable</span> <span class="synType">var</span> cornerRadius<span class="synSpecial">:</span> <span class="synType">CGFloat</span> <span class="synIdentifier">=</span> <span class="synConstant">0</span> {
<span class="synStatement">didSet</span> {
<span class="synIdentifier">self</span>.layer.cornerRadius <span class="synIdentifier">=</span> cornerRadius
<span class="synIdentifier">self</span>.layer.masksToBounds <span class="synIdentifier">=</span> <span class="synConstant">true</span>
}
}
<span class="synComment">// 「レビューのおねがい」部分のテキスト</span>
<span class="synType">@IBInspectable</span> <span class="synType">var</span> titleText<span class="synSpecial">:</span> <span class="synType">String</span> <span class="synIdentifier">=</span> <span class="synConstant">""</span> {
<span class="synStatement">didSet</span> {
titleLabel.text <span class="synIdentifier">=</span> titleText
}
}
<span class="synComment">// アルパカが表示されている画像</span>
<span class="synType">@IBInspectable</span> <span class="synType">var</span> iconImage<span class="synSpecial">:</span> <span class="synType">UIImage?</span> {
<span class="synStatement">didSet</span> {
iconImageView.image <span class="synIdentifier">=</span> iconImage
}
}
<span class="synComment">// 「ALPACAを応援する」ボタンのテキスト</span>
<span class="synType">@IBInspectable</span> <span class="synType">var</span> buttonTitle<span class="synSpecial">:</span> <span class="synType">String</span> <span class="synIdentifier">=</span> <span class="synConstant">""</span> {
<span class="synStatement">didSet</span> {
okButton.setTitle(buttonTitle, forState<span class="synSpecial">:</span> .Normal)
}
}
</pre>
<p>カスタムクラスのプロパティは、実はこれまでも <strong>User Defined Runtime Attributes</strong> を使えば値のセットは可能でした。</p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150725/20150725233632.png" alt="User Defined Runtime Attiributes よりも IBInspectable を使おう" title="User Defined Runtime Attiributes よりも IBInspectable を使おう" class="hatena-fotolife" itemprop="image" style="width:300px; border:1px solid #ccc"><br><span style="font-size: 90%"><span style="color: #999999"><i>User Defined Runtime Attributes</i></span></span></p>
<p>しかし、</p>
<ul>
<li>不正な値をセットしてしまうとクラッシュしてしまう</li>
<li>ここの存在を知らない開発者がいると動作を理解しづらい</li>
</ul>
<p>など使いづらい部分があったため、今後は IBInspectable を使うのが良いでしょう。</p>
<h1>使い方</h1>
<p>以上でカスタムView側の実装は完成です。<br />
最後にこのカスタムViewの使い方です。</p>
<h5>Storyboard/xibから初期化して使う場合</h5>
<p>UIView を Storyboard に貼り付け、クラス名に <strong>MyCustomView</strong> を指定します。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150726/20150726001117.gif" alt="f:id:himaratsu:20150726001117g:plain" width="616" height="618" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>Storyboard上の表示を確認しながら値を変更します。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150726/20150726001213.gif" alt="f:id:himaratsu:20150726001213g:plain" width="616" height="622" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h5>コードから初期化して使う場合</h5>
<p>frame または AutoLayout の制約でサイズを指定し、addSubview して使います。</p>
<pre class="code lang-swift" data-lang="swift" data-unlink><span class="synPreProc">let</span> <span class="synIdentifier">customView</span> <span class="synIdentifier">=</span> MyCustomView(frame<span class="synSpecial">:</span> <span class="synType">CGRectMake</span>(<span class="synConstant">50</span>, <span class="synConstant">200</span>, <span class="synConstant">280</span>, <span class="synConstant">200</span>))
view.addSubview(customView)
</pre>
<h1>まとめ</h1>
<p>カスタムViewをNibから初期化し、IBDesignable と IBInspectable を利用して便利に使えるようにする手順でした。<br />
より良い方法、より簡単な方法があれば教えていただけますと幸いです。</p>
<h1>サンプルコード</h1>
<p>今回使ったコードはこちらに置いています。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fhimaratsu%2FCustomViewSample" title="GitHub - himaratsu/CustomViewSample: how to create custom UIView from nib and @IBDesignable confirmed" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/himaratsu/CustomViewSample">github.com</a></cite></p>
<h1>参考資料</h1>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fqiita.com%2Fgonsee%2Fitems%2F230cea1ee511d54b3e85" title="UIViewをNibから初期化する - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://qiita.com/gonsee/items/230cea1ee511d54b3e85">qiita.com</a></cite></p>
<h1>オススメ書籍</h1>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4798043656?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51AyAHn4B2L._SL500_.jpg" class="hatena-asin-detail-image" alt="TECHNICAL MASTERはじめてのiOSアプリ開発Swift対応版" title="TECHNICAL MASTERはじめてのiOSアプリ開発Swift対応版"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4798043656?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">TECHNICAL MASTERはじめてのiOSアプリ開発Swift対応版</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C4%B9%C3%AB%C0%EE%20%C3%D2%B4%F5" class="keyword">長谷川 智希</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%A8%CF%C2%A5%B7%A5%B9%A5%C6%A5%E0">秀和システム</a></li></ul><a href="https://www.amazon.co.jp/dp/4798043656?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div>
初期設定から CocoaPods を使った実践チックな内容までを1冊で学習できます。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B00XKGB2K8?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51YcR0juYSL._SL500_.jpg" class="hatena-asin-detail-image" alt="iOSアプリ開発 AutoLayout徹底攻略 (Mynavi Advanced Library)" title="iOSアプリ開発 AutoLayout徹底攻略 (Mynavi Advanced Library)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B00XKGB2K8?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">iOSアプリ開発 AutoLayout徹底攻略 (Mynavi Advanced Library)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%BF%B9%20%B9%AA%BE%B0" class="keyword">森 巧尚</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%CA%A5%D3%BD%D0%C8%C7">マイナビ出版</a></li></ul><a href="https://www.amazon.co.jp/dp/B00XKGB2K8?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div>
AutoLayoutの理解を深めたい方にオススメです。</p>
himaratsu
「iOSアプリ テスト自動化入門」を読みました
hatenablog://entry/8454420450088575947
2015-03-19T22:09:28+09:00
2022-02-24T19:50:48+09:00 そろそろテストをちゃんと勉強しようと思って、以前から気になっていたこの本を読んでみました。 iOSアプリテスト自動化入門作者:長谷川 孝二秀和システムAmazon iOSアプリのテストや自動化まわりの話をまとめた本で、テストの意義や考え方、書き方などが丁寧に書かれています。 色々と勉強になったので、心と頭に残ったポイントをまとめてみます。
<p>そろそろテストをちゃんと勉強しようと思って、以前から気になっていたこの本を読んでみました。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4798040894?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/515ujXKjr6L._SL500_.jpg" class="hatena-asin-detail-image" alt="iOSアプリテスト自動化入門" title="iOSアプリテスト自動化入門"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4798040894?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">iOSアプリテスト自動化入門</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C4%B9%C3%AB%C0%EE%20%B9%A7%C6%F3" class="keyword">長谷川 孝二</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%A8%CF%C2%A5%B7%A5%B9%A5%C6%A5%E0">秀和システム</a></li></ul><a href="https://www.amazon.co.jp/dp/4798040894?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>アプリのテストや自動化まわりの話をまとめた本で、テストの意義や考え方、書き方などが丁寧に書かれています。
色々と勉強になったので、心と頭に残ったポイントをまとめてみます。</p>
<h2>読む前の状態</h2>
<ul>
<li>テストについてちゃんと勉強したことはない</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>のテストは、モデル周りについて少し書いたことがある</li>
<li>テスト書いておくと変更に強いな、安心して変更できるなと感じている</li>
<li>イケてるエンジニアはテストを書いている</li>
</ul>
<h2>読む目的</h2>
<ul>
<li>具体的にテストを書いていく流れを知りたい</li>
<li>テストに関する断片的な情報を整理したい</li>
</ul>
<h2>読書メモ</h2>
<h3>テストしやすい設計を心がける</h3>
<p>テストを書く副次的な効果として、意識的にテストをしやすい設計(=関心の分離ができた良い設計)をすることがあります。本の中では「テスタビリティの高い設計」と書かれていて、今後コードを書く上でこの言葉は胸に秘めておこうと思いました。</p>
<p>「意図の明確なコードを書く」という意味でいうとリーダブルコードを読む(読み返す)のも効果的かと感じます。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4873115655?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51MgH8Jmr3L._SL500_.jpg" class="hatena-asin-detail-image" alt="リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)" title="リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4873115655?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/Dustin%20Boswell" class="keyword">Dustin Boswell</a>,<a href="http://d.hatena.ne.jp/keyword/Trevor%20Foucher" class="keyword">Trevor Foucher</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%E9%A5%A4%A5%EA%A1%BC%A5%B8%A5%E3%A5%D1%A5%F3">オライリージャパン</a></li></ul><a href="https://www.amazon.co.jp/dp/4873115655?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<h3>既存コードにテストを追加する</h3>
<p>新しく生まれるコードにはテストを書いていくとして、業務などでは既存アプリに加わる or 引き継ぐことの方が多いかと思います。その場合でもテストを追加することは有用です。</p>
<p>なにか不具合が発生してそれを修正する場合に、</p>
<ul>
<li>1.まずはテストを書き、ちゃんと失敗することを確認する</li>
<li>2.次に実装を修正する</li>
<li>3.テストが通ることを確認する</li>
</ul>
<p>と進めていくことで、安心感が得られますし、今後同じ実装周りに変更を加えた時の資産になるというのは良いなと思いました。</p>
<p>自分がある程度把握している新規アプリよりも、全容を掴めぬまま修正する必要のある既存アプリのテストの方が重要かもしれませんね。</p>
<h3>テストが書けない状態の場合</h3>
<p>テスタビリティが考えられてないコードに途中からテストを追加するのは困難です。この場合は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>してテスタビリティを向上させつつテストを追加していく必要があります。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>しつつテストを書いていくのは当然コストがかかりますので、バランスをみて<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>するか諦めるかを判断するのも重要、と書かれていました。</p>
<p>リファクタしつつ進めていく参考として以下の書籍が紹介されていました。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4798116831?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51dVODTDz-L._SL500_.jpg" class="hatena-asin-detail-image" alt="レガシーコード改善ガイド (Object Oriented SELECTION)" title="レガシーコード改善ガイド (Object Oriented SELECTION)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4798116831?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">レガシーコード改善ガイド (Object Oriented SELECTION)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%B1%A5%EB%A1%A6C%A1%A6%A5%D5%A5%A7%A5%B6%A1%BC%A5%BA" class="keyword">マイケル・C・フェザーズ</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%E6%C6%B1%CB%BC%D2">翔泳社</a></li></ul><a href="https://www.amazon.co.jp/dp/4798116831?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<h3>振る舞い駆動開発(BDD)</h3>
<p>本の中ではテスト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>のKiwiを例に、BDDについて説明がありました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fkiwi-bdd%2FKiwi" title="GitHub - kiwi-bdd/Kiwi: Simple BDD for iOS" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/kiwi-bdd/Kiwi">github.com</a></cite></p>
<p>Kiwiでは、以下のようにSpec(仕様)の形でテストを書いていくことができます。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink><span class="synIdentifier">describe</span>(<span class="synConstant">@"Team"</span>, ^{
context(<span class="synConstant">@"when newly created"</span>, ^{
it(<span class="synConstant">@"has a name"</span>, ^{
<span class="synType">id</span> team = [Team team];
[[team.name should] equal:<span class="synConstant">@"Black Hawks"</span>];
});
it(<span class="synConstant">@"has 11 players"</span>, ^{
<span class="synType">id</span> team = [Team team];
[[[team should] have:<span class="synConstant">11</span>] players];
});
});
});
</pre>
<p>記法に関する詳しい説明は省略しますが、このようにSpecを書いていくことで、まるでテストケースが仕様ドキュメントのように作られていきます。<br />
後から入るメンバーのために仕様をドキュメント化するのは重要ですが、面白さが少なくついサボりがちになってしまいます。テストを書くことで仕様がまとめられるのはとても良いアプローチだなと思いました。</p>
<p>なお、Kiwiの詳細な使い方は以下が詳しいです。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fmixi-inc%2FiOSTraining%2Fwiki%2F11.3-Kiwi%25E3%2582%2592%25E7%2594%25A8%25E3%2581%2584%25E3%2581%259F%25E6%258C%25AF%25E3%2582%258B%25E8%2588%259E%25E3%2581%2584%25E3%2583%2586%25E3%2582%25B9%25E3%2583%2588" title="11.3 Kiwiを用いた振る舞いテスト · mixi-inc/iOSTraining Wiki" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/mixi-inc/iOSTraining/wiki/11.3-Kiwi%E3%82%92%E7%94%A8%E3%81%84%E3%81%9F%E6%8C%AF%E3%82%8B%E8%88%9E%E3%81%84%E3%83%86%E3%82%B9%E3%83%88">github.com</a></cite></p>
<h3>Target / Configuration / <a class="keyword" href="http://d.hatena.ne.jp/keyword/Scheme">Scheme</a></h3>
<p>様々なケースにでテストを対応させようという文脈で説明された<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a>に関する情報も、自分の知識の整理にとても役立ちました。</p>
<ul>
<li>開発環境と本番環境をどう切り替えてテストするのか?</li>
<li>スキームの"Shared"チェック</li>
<li>xcconfigファイルの使い方</li>
</ul>
<p>など、これまでWebで断片的に聞いたり試したりしていた情報を体系立てて理解することができました。</p>
<p>以上、読書メモでした。</p>
<h2>試そうと思うテスト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>まとめ</h2>
<h5>Kiwi</h5>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fkiwi-bdd%2FKiwi" title="GitHub - kiwi-bdd/Kiwi: Simple BDD for iOS" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/kiwi-bdd/Kiwi">github.com</a></cite></p>
<p>BDDで書ける。モックや非同期処理にも対応。</p>
<h5>KIF</h5>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fkif-framework%2FKIF" title="GitHub - kif-framework/KIF: Keep It Functional - An iOS Functional Testing Framework" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/kif-framework/KIF">github.com</a></cite></p>
<p>Square社製の統合テスト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>。View周りのテストなどに使いたい。</p>
<p>参考<br />
<iframe src="https://www.slideshare.net/slideshow/embed_code/key/GJz7QrZoyVc7qz" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/kitasuke/iosui" title="iOSにおけるUIテスト@potetotips" target="_blank">iOSにおけるUIテスト@potetotips</a> </strong> from <strong><a href="https://www.slideshare.net/kitasuke" target="_blank">Yusuke Kita</a></strong> </div> <cite class="hatena-citation"><a href="http://www.slideshare.net/kitasuke/iosui">www.slideshare.net</a></cite></p>
<h2>感想</h2>
<p>テストへの考え方から実際の書き方まで、コードつきで説明が掲載されていて初心者の自分でも非常に分かりやすかったです。特に前半の考え方の部分にあった「テスタビリティの高い設計を心がける」「既存アプリの不具合修正の時にまずテストを書く」というのが印象的で、早速明日からやっていこうと思います。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4798040894?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/515ujXKjr6L._SL500_.jpg" class="hatena-asin-detail-image" alt="iOSアプリテスト自動化入門" title="iOSアプリテスト自動化入門"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4798040894?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">iOSアプリテスト自動化入門</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C4%B9%C3%AB%C0%EE%20%B9%A7%C6%F3" class="keyword">長谷川 孝二</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%A8%CF%C2%A5%B7%A5%B9%A5%C6%A5%E0">秀和システム</a></li></ul><a href="https://www.amazon.co.jp/dp/4798040894?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<h2>関連するおすすめ書籍</h2>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B00JEYPPOE?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51LZpcbh3LL._SL500_.jpg" class="hatena-asin-detail-image" alt="Code Complete 第2版 上 完全なプログラミングを目指して" title="Code Complete 第2版 上 完全なプログラミングを目指して"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B00JEYPPOE?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">Code Complete 第2版 上 完全なプログラミングを目指して</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%C6%A5%A3%A1%BC%A5%D6%20%A5%DE%A5%B3%A5%CD%A5%EB" class="keyword">スティーブ マコネル</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C6%FC%B7%D0BP">日経BP</a></li></ul><a href="https://www.amazon.co.jp/dp/B00JEYPPOE?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4894717115?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51G6YEDVRKL._SL500_.jpg" class="hatena-asin-detail-image" alt="テスト駆動開発入門" title="テスト駆動開発入門"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4894717115?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">テスト駆動開発入門</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%A5%B1%A5%F3%A5%C8%20%A5%D9%A5%C3%A5%AF" class="keyword">ケント ベック</a></li><li>ピアソンエデュケーション</li></ul><a href="https://www.amazon.co.jp/dp/4894717115?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
himaratsu
健康にコードを書き続けるために骨に気をつける
hatenablog://entry/8454420450085888016
2015-03-17T22:58:41+09:00
2022-02-24T19:50:53+09:00 少し大きめのライフイベントがあったので、それに向け人生初の整体に行ってきました。 正確にはカイロプラクティックといって、アメリカなどでは割とある療法らしく、骨を良い感じに調整して健康でいきましょうみたいなものです(曖昧)。 先生の施術に感動したのと、毎日パソコンと向き合っていても健康を維持する方法を聞いたので、メモしておきます。
<p>少し大きめのライフイベントがあったので、それに向け人生初の整体に行ってきました。<br />
正確には<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A5%A4%A5%ED%A5%D7%A5%E9%A5%AF%A5%C6%A5%A3%A5%C3%A5%AF">カイロプラクティック</a>といって、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%E1%A5%EA">アメリ</a>カなどでは割とある療法らしく、骨を良い感じに調整して健康でいきましょうみたいなものです(曖昧)。</p>
<p>先生の施術に感動したのと、毎日パソコンと向き合っていても健康を維持する方法を聞いたので、メモしておきます。</p>
<h2>はじめてのカイロプラティック</h2>
<p>はじめに全身を見てもらい、調子の悪い部分(背中/肩まわり)を触診で当てられ、その部分メインで施術してもらいました。</p>
<p>肩には全く触れず、首の骨の位置を正すだけで魔法のように肩が軽くなったり、背骨を1つずつ矯正して猫背が楽になったりと、人間の体の構造の不思議さに驚きの連続でした。</p>
<p>猫背などの場合、骨だけでなく筋肉にもクセがついているらしく、骨を矯正した後はマッサージで骨の回りの筋肉をほぐしてもらって、大体1時間ほどで施術は終了しました。</p>
<h2>健康にコーディングするために</h2>
<p>マッサージや整体って、その時間は気持ちよくても、またすぐ姿勢が悪くなってしまうんじゃないか?と聞いたところ、今日の施術で変なクセは取れたので、次のことに気をつければ良いというアド<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>をもらいました。</p>
<h3>①寝る前に骨の運動をする</h3>
<p>筋肉の運動であるラジオ体操は朝に行いますが、<strong>骨の運動は寝る前にする</strong>のが良いらしいです。<br />
運動といっても大したことではなくて、首や肩を回したり、1分程度柔軟したりを「左右対称」にやれば良いとのこと。</p>
<p>何も動かずバタリと寝てしまうと、例えば右利きの場合は骨が右に寄ってしまうらしく、左右のバランスが悪くなりその結果疲れやすい体になってしまうそうです。</p>
<h3>②モニタは目線より上に</h3>
<p>モニタを見続けるのは職業柄仕方ないと思いますが、モニタの位置を目線より上にすればかなり肩は凝りにくくなるそうです。
ノートパソコンの場合はどうしても目線より下になってしまいますが、↓のようなスタンドを使うと良さそう。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B000NTQNAO?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51u4tTTOFwL._SL500_.jpg" class="hatena-asin-detail-image" alt="サンワサプライ ノートパソコンスタンド CR-35" title="サンワサプライ ノートパソコンスタンド CR-35"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B000NTQNAO?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">サンワサプライ ノートパソコンスタンド CR-35</a></p><ul class="hatena-asin-detail-meta"><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%F3%A5%EF%A5%B5%A5%D7%A5%E9%A5%A4">サンワサプライ</a>(Sanwa Supply)</li></ul><a href="https://www.amazon.co.jp/dp/B000NTQNAO?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>ちなみに会社の先輩はこのスタンドを使っていて、肩が全然凝らないと言ってました。スタンディングデスクにするのも良いと思います。</p>
<h3>③腰の下あたりに力を入れて、グッと胸を張る</h3>
<p>猫背にならないよう、意識して姿勢を正すという当たり前の話です。<br />
これまではキツくてなかなか保てなかったのですが、骨と筋肉のクセをほぐしてくれたので、今までよりも楽に姿勢を正せるそうです。(2週間ほど経過しましたが確かに楽に保てる)</p>
<h1>感想</h1>
<p>ネットで調べてみると、整体/カイロプラティックは先生によって当たりハズレがあるみたいです。<br />
今回お願いした先生は知り合いに紹介してもらったのですが、有名な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B9%A5%DD%A1%BC%A5%C4">プロスポーツ</a>選手とかも見てる方でとても快適でした。</p>
<p>教えてもらったポイントを忘れずに、長く健康でいたいなと思いました。以上、はじめてのカイロプラティック体験でした。</p>
<h1>関連リンク</h1>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/B00FAXNM2A?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/41SolyAmg6L._SL500_.jpg" class="hatena-asin-detail-image" alt="The Healthy Programmer: Get Fit, Feel Better, and Keep Coding (Pragmatic Programmers) (English Edition)" title="The Healthy Programmer: Get Fit, Feel Better, and Keep Coding (Pragmatic Programmers) (English Edition)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/B00FAXNM2A?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">The Healthy Programmer: Get Fit, Feel Better, and Keep Coding (Pragmatic Programmers) (English Edition)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/Kutner%2C%20Joe" class="keyword">Kutner, Joe</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Pragmatic%20Bookshelf">Pragmatic Bookshelf</a></li></ul><a href="https://www.amazon.co.jp/dp/B00FAXNM2A?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fblog.8arrow.org%2Fentry%2F2015%2F02%2F11%2F152139" title="「The Healthy Programmer」を読んで自宅を快適なプログラミング環境にする - 八発白中" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4480068228?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/41UGfj2kxqL._SL500_.jpg" class="hatena-asin-detail-image" alt="カラダが変わる! 姿勢の科学 (ちくま新書)" title="カラダが変わる! 姿勢の科学 (ちくま新書)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4480068228?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">カラダが変わる! 姿勢の科学 (ちくま新書)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C0%D0%B0%E6%20%C4%BE%CA%FD" class="keyword">石井 直方</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C3%DE%CB%E0%BD%F1%CB%BC">筑摩書房</a></li></ul><a href="https://www.amazon.co.jp/dp/4480068228?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p><a href="https://www.amazon.co.jp/exec/obidos/ASIN/4047315672/samura1-22/">[asin:4047315672:detail]</a></p>
<p>カイロプラティックについて知識足らずのため、何か誤り等ありましたらご指摘いただけると助かりますmm</p>
himaratsu
第15回はSansan開催! #potatotips で発表されたiOSとAndroidのtipsまとめ
hatenablog://entry/8454420450087936972
2015-03-13T08:29:55+09:00
2022-02-24T20:50:59+09:00 第15回となる #potatotips に参加させて頂きました。 今回は名刺管理アプリEightでおなじみのSansan株式会社@青山での開催でした。 https://github.com/potatotips/potatotips/wiki/Potatotips-15
<p>第15回となる #potatotips に参加させて頂きました。<br />
今回は<a href="https://8card.net/">名刺管理アプリEight</a>でおなじみの<a href="http://jp.corp-sansan.com/">Sansan株式会社</a>@青山での開催でした。
<a href="https://github.com/potatotips/potatotips/wiki/Potatotips-15">https://github.com/potatotips/potatotips/wiki/Potatotips-15</a></p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20150313/20150313013437.jpg" alt="f:id:himaratsu:20150313013437j:plain" width="800" height="600" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>potatotipsは<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>や<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>の情報を持ち時間1人5分で発表するtips共有会です。<br />
今回は「ブログまとめ枠」が新設されたので、その枠で参加させていただきました。</p>
<p>そんな第15回で発表された<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>/<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>のtipsをまとめます!</p>
<h3>Microframeworks</h3>
<ul>
<li><a href="https://twitter.com/cockscomb">@cockscomb</a>さん</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>におけるmicroservicesのようなもの</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/MVC">MVC</a>のうちModelにあたる部分をMicroframeworksにすると良いことがたくさんある
<ul>
<li>設計が良くなる</li>
<li>テストを書くことが必要になる</li>
<li>(うまくかけば)<a class="keyword" href="http://d.hatena.ne.jp/keyword/OS%20X">OS X</a>とも共<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%CC%B2%BD">通化</a>できる</li>
</ul>
</li>
<li>逆に悪いところ
<ul>
<li>2週間くらいで作る軽めのアプリには向かない</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 7で使えない</li>
</ul>
</li>
<li><script async class="speakerdeck-embed" data-id="f7f519def7e44414b0df3a0c9507eda4" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h3>Viewの共<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%CC%B2%BD">通化</a>方法まとめ</h3>
<ul>
<li><a href="https://twitter.com/konifar">@konifar</a> さん</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>のViewの共<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%CC%B2%BD">通化</a>のパターンと使いどころについて</li>
<li>styles.<a class="keyword" href="http://d.hatena.ne.jp/keyword/xml">xml</a> / <include /> / CustomView
<ul>
<li>複数のViewを持つか?ロジックが絡むか?で分岐する</li>
</ul>
</li>
<li><script async class="speakerdeck-embed" data-id="6634333fbc63488e87f9b5e762b3c19b" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h3>Webと<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>アプリでパスワードを共有する(Shared Web Credentialについて)</h3>
<ul>
<li><a href="https://twitter.com/k_katsumi">@k_katsumi</a> さん</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8では、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>はパスワード情報を記録してくれる</li>
<li>アプリから<a class="keyword" href="http://d.hatena.ne.jp/keyword/Safari">Safari</a>の記録したKeychain情報にアクセス</li>
<li>Webでログインしたらアプリでもその情報を使う、を実現できる</li>
</ul>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fblog.kishikawakatsumi.com%2Fentry%2F2015%2F03%2F12%2F171116" title="WebとiOSアプリでパスワードを共有する - 24/7 twenty-four seven" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p><a href="http://kishikawakatsumi.hatenablog.com/entry/2015/03/12/171116">WebとiOSアプリでパスワードを共有する - 24/7 twenty-four seven</a></p>
<h3>Gradle Tips</h3>
<ul>
<li><a href="https://twitter.com/anton0825">@anton0825</a> さん</li>
<li>Gradleに関するtipsを紹介</li>
<li>Product Flavor
<ul>
<li>Pro版 / Free版など、少しだけ仕様が異なるAPKをうまく生成する方法</li>
</ul>
</li>
<li>Icon Versioning
<ul>
<li>アイコン上にbranch名やcommit<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%B7%A5%E5%C3%CD">ハッシュ値</a>を載せる方法</li>
</ul>
</li>
<li><a href="http://hosokawa0825.github.io/slides/GradleTips/#/">http://hosokawa0825.github.io/slides/GradleTips/#/</a></li>
</ul>
<h3>Introducing Tuna</h3>
<ul>
<li><a href="https://twitter.com/dealforest">@dealforest</a>さん</li>
<li>自作した<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> plugin「Tuna」の紹介
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>を非常に楽にしてくれる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3">プラグイン</a></li>
<li>"プリント<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>をビルドしなおさないでできるやつ"</li>
</ul>
</li>
<li>便利そう!</li>
<li><script async class="speakerdeck-embed" data-id="6f4c167129a74153838f35bc5c5c9c46" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
<li><a href="https://github.com/dealforest/Tuna">Tuna | GitHub</a></li>
</ul>
<h3>ボタンとラベルだけでカレンダーを作ってみた(祝祭日含む)</h3>
<ul>
<li><a href="https://github.com/fumiyasac">fumiyasac</a>さん</li>
<li>ライブラリを使わず自作でカレンダーを作った話
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Objective-C">Objective-C</a>で & Swiftで</li>
</ul>
</li>
<li>祝祭日ロジックやハッピーマンデー法などの考慮に苦労した</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/45746961" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/fumiyasakai37/15potatotips" title="ハンドメイドカレンダー第15回potatotips用" target="_blank">ハンドメイドカレンダー第15回potatotips用</a> </strong> from <strong><a href="//www.slideshare.net/fumiyasakai37" target="_blank">Fumiya Sakai</a></strong> </div></li>
</ul>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>アプリの滞在時間の計測</h3>
<ul>
<li><a href="https://twitter.com/heki1224">@heki1224</a>さん</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>アプリの滞在時間を計測したい
<ul>
<li>簡単にとるなら<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Analytics">Google Analytics</a></li>
<li>Application.ActivityLifecycleCallbacks を使って自前で実装もできる</li>
</ul>
</li>
</ul>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>で無限バックグ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%A6%A5%F3%A5%C9%A5%A2%A5%C3%A5%D7">ラウンドアップ</a>ロード</h3>
<ul>
<li><a href="https://twitter.com/ainame">@ainame</a>さん</li>
<li>写真のアップロード機能、よくある「N枚まで選択できます」の仕様はフォアグラウンドが前提</li>
<li>無限に、バックグラウンドでアップロードできるものを作った
<ul>
<li>NSURLSessionConfiguration#backgroundSessionConfiguration を使った方法ではできなかった</li>
<li>アップロード成功のたびにSilentPushを打つ方法でできた</li>
</ul>
</li>
<li><script async class="speakerdeck-embed" data-id="f89e92c4cdc245baa5c028e5596e3f8a" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h5>注意</h5>
<p>Silent Pushには制限があるため、この方法では無限アップロードにならない可能性があるようです。<br />
岸川さんのツイートをお借りさせて頂きますm(__)m</p>
<p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/potatotips?src=hash&ref_src=twsrc%5Etfw">#potatotips</a> レートリミットがどういう基準でかかるかは非公開ですが、以前に試した時は10分おき、くらいの間隔でも数時間続けるとPush通知が届かなくなります。</p>— kishikawa katsumi (@k_katsumi) <a href="https://twitter.com/k_katsumi/status/575973422276050946?ref_src=twsrc%5Etfw">2015年3月12日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p>
<p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Silent Pushのレートリミットを含む挙動についてについて検証した記事 <a href="http://t.co/8x9GMIr6or">http://t.co/8x9GMIr6or</a> <a href="https://twitter.com/hashtag/potatotips?src=hash&ref_src=twsrc%5Etfw">#potatotips</a></p>— kishikawa katsumi (@k_katsumi) <a href="https://twitter.com/k_katsumi/status/575976737709813760?ref_src=twsrc%5Etfw">2015年3月12日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p>
<h3>アプリにおけるおもてなしTips</h3>
<ul>
<li><a href="https://twitter.com/shobyshoby">@shobyshoby</a>さん</li>
<li>ユーザーへのおもてなしをやる
<ul>
<li>エラーでビックリさせない</li>
<li>ボタン押す恐怖を和らげる</li>
<li>待ち時間のイライラを減らす</li>
<li>頑張って入力されたデータを守る</li>
<li>前の画面にも変更を反映</li>
</ul>
</li>
<li><script async class="speakerdeck-embed" data-id="a3a6d464942e44deb53d5a72ffc68c52" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h3>Effective UIScrollView</h3>
<ul>
<li><a href="https://twitter.com/hedjirog">@hedjirog</a>さん</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/WWDC">WWDC</a>でも人気のUIScrollViewのネタ</li>
<li>ScrollViewの背面と上にUIButtonがある時、どのように実装するのが良いか
<ul>
<li>UIPanGestureRecognizer と hitTest で実装</li>
</ul>
</li>
<li><script async class="speakerdeck-embed" data-id="133700d33c5a44af87683a5eff12e5cb" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h3>CircleCIで消耗してみた話</h3>
<ul>
<li><a href="https://twitter.com/huin">@huin</a>さん</li>
<li>CircleCIの処理にかかる時間を計測し、それを改善した話
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>群のキャッシュ</li>
<li>disablePreDexオプション</li>
<li>Robolectric導入</li>
</ul>
</li>
<li><script async class="speakerdeck-embed" data-id="75daf625464f4a9e8e51dc97038aa7d3" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h3>Introducing APIKit</h3>
<ul>
<li><a href="https://twitter.com/_ishkawa">@_ishkawa</a>さん</li>
<li>Swiftらしく書ける<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>クライアント「APIKit」を作った話</li>
<li>せっかくのSwiftで書いているのに、堅牢にかけてない場合がある
<ul>
<li>APIKitを使うことで安全で使いやすく</li>
</ul>
</li>
<li>ドキュメントをそのまま写したかのように美しく書ける</li>
<li><script async class="speakerdeck-embed" data-id="d047462f9c0c44d1aa60990c676016e3" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h3>GooglePlayへのアップロード自動化を試してみた</h3>
<ul>
<li><a href="https://twitter.com/Horie1024">@Horie1024</a>さん</li>
<li><a href="http://tech.vasily.jp/circleci_deploygate_android_app_automation/">CircleCIを使ってパッケージを検証配布</a> / <a href="http://qiita.com/Horie1024/items/0d3d50405f0b4bef1792">GooglePlay API を使ってアップロード</a> はできた</li>
<li>CircleCI から GooglePlay に自動でアップロードしてほしい</li>
<li>作ってたが探したらあった
<ul>
<li><a href="https://github.com/Triple-T/gradle-play-publisher">gradle-play-publisher | GitHub</a></li>
</ul>
</li>
<li><script async class="speakerdeck-embed" data-id="6c4f4945c10c41bdbc36670c5070c6e8" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h3>WatchKitにおける<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a> Appとのデータ共有</h3>
<ul>
<li><a href="https://twitter.com/akio0911">@akio0911</a>さん</li>
<li>WatchKitの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>について</li>
<li>本体とAppleWatchのデータ共有について
<ul>
<li>AppGroup / UserDefaults / openParentApplication:reply:</li>
<li>それぞれの方法をどう使い分ければ良いか?</li>
</ul>
</li>
<li><script async class="speakerdeck-embed" data-id="3e2d130946f24de5b2d6f38c31e5a3be" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h3>Realmビギナーが知っとくべき内容で打線組んだwww</h3>
<ul>
<li><a href="https://twitter.com/yimajo">@yimajo</a>さん</li>
<li><a href="https://github.com/realm/realm-cocoa">Realm</a> の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%A2%A4%EB%A4%A2%A4%EB%A5%CD%A5%BF">あるあるネタ</a>を紹介
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/nil">nil</a>の扱いが難しく、WebAPIからデータを取ってくる場合などは大変</li>
<li>Dateではミリ秒を扱えない</li>
<li><a href="https://github.com/matthewcheok/Realm-JSON">Realm-JSON</a> で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%C3%A5%D4%A5%F3%A5%B0">マッピング</a>ルール書いて使うと便利</li>
</ul>
</li>
<li><script async class="speakerdeck-embed" data-id="dd19c7ac2f0444d0a997e3d14b357901" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h1>まとめ</h1>
<p>いつもは<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>のtipsだけをピックアップしていましたが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/mixi">mixi</a>さんの<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>研修に参加させてもらって雰囲気を分かってきたので、今回は両OS分まとめてみました。
両方分かるとpotatotipsは2倍楽しい!発表すればさらに楽しいので、次回は久しぶりに発表枠で参加したいと思います。</p>
<p>potatotipsは毎回connpassページにて発表者を募集しています。(<a href="http://connpass.com/event/12791/">第16回の募集はこちら</a>)
主催してくれる会社さんも募集されているようですので、興味のある方はぜひチェックしてみてください!</p>
<p>発表者のみなさん、Sansanのみなさん、本日はありがとうございました!</p>
<h1>関連記事</h1>
<ul>
<li>過去に開催されたポテチのまとめ記事はこちらです
<ul>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips1">クックパッドのLT会に参加してきたのでiOSのtipsをまとめる</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips2">第2回 #potatotips に参加してきたのでiOSのtipsをまとめる</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips3">第3回はヤフー開催! #potatotips で発表されたiOSのtipsまとめ</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips4">第4回 #potatotips で発表されたiOSに関する9つのtips</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips5">第5回 #potatotips で発表された12個のiOSのtipsをまとめる</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips6">第6回はUIEvolution開催! #potatotips で発表されたiOSのtipsまとめ</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips7">第7回はDeNA開催! #potatotips で発表されたiOSのtipsまとめ</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips9">第9回はFablic開催! #potatotips で発表されたiOSのtipsまとめ</a></li>
</ul>
</li>
</ul>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20131113/20131113234202.jpg" alt="f:id:himaratsu:20131113234202j:plain" title="f:id:himaratsu:20131113234202j:plain" class="hatena-fotolife" itemprop="image"></span></p>
himaratsu
年末年始に読みたいSwift勉強のためのおすすめ本・書籍やサイトなど(追記あり)
hatenablog://entry/8454420450077722200
2014-12-22T21:13:02+09:00
2022-02-24T19:50:49+09:00 この記事は Swift Advent Calendar 2014 の22日目の記事です。 21日目は MeguMegu1978 さんの ローカルルールをSwiftで でした。 はじめに Swift が発表されて半年が経ちました。仕事やプライベートの開発で Swift は書いてますが、記法や設計など、もっと良い方法があるのではないか?といつも思っています。 日常ではまとまった時間を確保するのは難しい、まとまった時間のとれる年末年始に Swift 再入門するぞ! そんな思いでSwift勉強のための書籍・サイトをリストアップしてみました。 Apple公式資料 まずは公式の資料です。
<p>この記事は Swift Advent Calendar 2014 の22日目の記事です。<br />
21日目は <a href="http://qiita.com/MeguMegu1978">MeguMegu1978</a> さんの <a href="http://qiita.com/MeguMegu1978/items/625a2906d2ee0573e3e0">ローカルルールをSwiftで</a> でした。</p>
<h1>はじめに</h1>
<p>Swift が発表されて半年が経ちました。仕事やプライベートの開発で Swift は書いてますが、記法や設計など、もっと良い方法があるのではないか?といつも思っています。</p>
<p>日常ではまとまった時間を確保するのは難しい、まとまった時間のとれる年末年始に Swift 再入門するぞ!<br />
そんな思いでSwift勉強のための書籍・サイトをリストアップしてみました。</p>
<h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a>公式資料</h1>
<p>まずは公式の資料です。</p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/iBooks">iBooks</a></h2>
<p><div class="itunes-embed freezed itunes-kind-ebook"><a href="https://books.apple.com/us/book/the-swift-programming-language-swift-5-5/id881256329?uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank"><img src="https://cdn.image.st-hatena.com/image/scale/25f89b5f6aab6ce0ed3637079afda3884d46fd32/enlarge=0;height=200;version=1;width=200/https%3A%2F%2Fis1-ssl.mzstatic.com%2Fimage%2Fthumb%2FPublication115%2Fv4%2F57%2F5c%2Fa6%2F575ca63f-d7e5-039a-8d4d-748cef2e689f%2Fcover.jpg%2F100x100bb.jpg" alt="The Swift Programming Language (Swift 5.5)" title="The Swift Programming Language (Swift 5.5)" class="itunes-embed-image"/></a><div class="itunes-embed-info"><p class="itunes-embed-title"><a href="https://books.apple.com/us/book/the-swift-programming-language-swift-5-5/id881256329?uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank">The Swift Programming Language (Swift 5.5)</a></p><ul><li class="itunes-embed-artist"><a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a> Inc.</li><li class="itunes-embed-genre">Programming</li><li class="itunes-embed-price">Free</li><li class="itunes-embed-badge"><a href="https://books.apple.com/us/book/the-swift-programming-language-swift-5-5/id881256329?uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank"><img src="https://cdn.blog.st-hatena.com/images/theme/itunes/itunes-badge-ibookstore@2x.png" width="64px" height="15px" /></a></li></ul></div></div></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/https">https</a>://<a class="keyword" href="http://d.hatena.ne.jp/keyword/itunes">itunes</a>.<a class="keyword" href="http://d.hatena.ne.jp/keyword/apple">apple</a>.com/us/book/using-swift-<a class="keyword" href="http://d.hatena.ne.jp/keyword/cocoa">cocoa</a>-objective/id888894773?mt=11&at=10l8JW&ct=hatenablog</p>
<p>これらには Web版も提供されていて、それぞれ以下で読むことが出来ます。</p>
<ul>
<li><a href="https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/index.html">The Swift Programming Language</a></li>
<li><a href="https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/#//apple_ref/doc/uid/TP40014216-CH2-XID_0">Using Swift with Cocoa and Objective-C</a></li>
</ul>
<h2>Swift Blog</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a> の公式ブログです。Swift に関する tips などが書かれています。</p>
<ul>
<li><a href="https://developer.apple.com/swift/blog/">Swift Blog - Apple Developer</a></li>
</ul>
<h2>書籍</h2>
<p>最近ポチったリストです。<br />
体系的な知識は書籍で学ぶのが良いんじゃないかと思っているので、少しずつ読んでいきたいです。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4798043656?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51AyAHn4B2L._SL500_.jpg" class="hatena-asin-detail-image" alt="TECHNICAL MASTERはじめてのiOSアプリ開発Swift対応版" title="TECHNICAL MASTERはじめてのiOSアプリ開発Swift対応版"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4798043656?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">TECHNICAL MASTERはじめてのiOSアプリ開発Swift対応版</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C4%B9%C3%AB%C0%EE%20%C3%D2%B4%F5" class="keyword">長谷川 智希</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%A8%CF%C2%A5%B7%A5%B9%A5%C6%A5%E0">秀和システム</a></li></ul><a href="https://www.amazon.co.jp/dp/4798043656?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>入門的な内容から、CocoaPodsを使った実践的な内容までを紹介した書籍。<br />
<a href="https://github.com/hasegawa-tomoki/GourmetSearch">コードの Swift のアップデートへの追従も丁寧</a>で、ハマりを防げてとても助かります。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4839953538?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/61mjW4VYyyL._SL500_.jpg" class="hatena-asin-detail-image" alt="Swiftではじめる iPhoneアプリ開発の教科書 【iOS 8&Xcode 6対応】" title="Swiftではじめる iPhoneアプリ開発の教科書 【iOS 8&Xcode 6対応】"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4839953538?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">Swiftではじめる iPhoneアプリ開発の教科書 【iOS 8&Xcode 6対応】</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%BF%B9%20%B9%AA%BE%B0" class="keyword">森 巧尚</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%CA%A5%D3">マイナビ</a></li></ul><a href="https://www.amazon.co.jp/dp/4839953538?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>「<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone%A5%A2%A5%D7%A5%EA">iPhoneアプリ</a>開発の教科書」シリーズで<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>開発に入門させてもらったので、Swift でもこのシリーズから学びたいと思って購入しました。著書名は <a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> 6 対応となっていますが、<a href="http://book.mynavi.jp/support/pc/5353/">サポートサイト</a>で <a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> 6.1 対応の差分が更新されているようです。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4861009499?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51WHtltDWLL._SL500_.jpg" class="hatena-asin-detail-image" alt="たのしいSwiftプログラミング―[iOS 8&Xcode 6対応]" title="たのしいSwiftプログラミング―[iOS 8&Xcode 6対応]"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4861009499?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">たのしいSwiftプログラミング―[iOS 8&Xcode 6対応]</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%CC%DA%B2%BC%20%C0%BF" class="keyword">木下 誠</a></li><li>ビー・エヌ・エヌ新社</li></ul><a href="https://www.amazon.co.jp/dp/4861009499?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p><a href="http://www.amazon.co.jp/gp/product/4861007348?ie=UTF8&camp=1207&creative=8411&creativeASIN=4861007348&linkCode=shr&tag=samura1-2">黄色い本</a>でお世話になった木下さんの本。アプリ版も出ていて、本を買ったらアプリ版も手に入るようになってるみたいです。サンプルアプリがその場で実行できる、みたいな機能があるみたいで楽しみです。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4797380497?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51YLVAWRtSL._SL500_.jpg" class="hatena-asin-detail-image" alt="詳解 Swift" title="詳解 Swift"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4797380497?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">詳解 Swift</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%B2%AE%B8%B6%20%B9%E4%BB%D6" class="keyword">荻原 剛志</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/SB%A5%AF%A5%EA%A5%A8%A5%A4%A5%C6%A5%A3%A5%D6">SBクリエイティブ</a></li></ul><a href="https://www.amazon.co.jp/dp/4797380497?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>「詳解 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Objective-C">Objective-C</a>」でお世話になった荻原さんの本。黒い本は何度も読ませて頂きました。「詳解 Swift」さんもこれからよろしくお願いします。</p>
<p><a href="https://www.amazon.co.jp/exec/obidos/ASIN/4839953546/samura1-22/">[asin:4839953546:detail]</a></p>
<p>まだ発売されてないのですが、献本レビュー記事が数回目にとまり、おもしろそうだったのでポチりました。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4774169552?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/61GuZ+7U5IL._SL500_.jpg" class="hatena-asin-detail-image" alt="WEB+DB PRESS Vol.84" title="WEB+DB PRESS Vol.84"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4774169552?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">WEB+DB PRESS Vol.84</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C6%A3%20%B8%E3%CF%BA" class="keyword">藤 吾郎</a>,<a href="http://d.hatena.ne.jp/keyword/%B7%AC%CC%EE%20%BE%CF%B9%B0" class="keyword">桑野 章弘</a>,<a href="http://d.hatena.ne.jp/keyword/%CA%A1%B1%CA%20%CF%CB" class="keyword">福永 亘</a>,<a href="http://d.hatena.ne.jp/keyword/%C3%AB%B0%E6%20%CC%F7%BB%CB" class="keyword">谷井 靖史</a>,<a href="http://d.hatena.ne.jp/keyword/%CC%EE%C2%BC%20%BF%B8%C7%B7%B2%F0" class="keyword">野村 晋之介</a>,<a href="http://d.hatena.ne.jp/keyword/%C9%C8%C0%EE%20%E2%AB%CA%BF" class="keyword">蛭川 皓平</a>,<a href="http://d.hatena.ne.jp/keyword/%B2%AC%C5%C4%20%CD%A7%CA%E5" class="keyword">岡田 友輔</a>,<a href="http://d.hatena.ne.jp/keyword/%C6%A3%CB%DC%20%BF%BF%BC%F9" class="keyword">藤本 真樹</a>,<a href="http://d.hatena.ne.jp/keyword/%B0%CB%C6%A3%20%C4%BE%CC%E9" class="keyword">伊藤 直也</a>,<a href="http://d.hatena.ne.jp/keyword/%B5%DC%BA%EA%20%CC%F7%C9%A7" class="keyword">宮崎 靖彦</a>,<a href="http://d.hatena.ne.jp/keyword/%BA%B4%C6%A3%20%B7%F2%C2%C0" class="keyword">佐藤 健太</a>,<a href="http://d.hatena.ne.jp/keyword/%B9%E2%B6%B6%20%BD%D3%B9%AC" class="keyword">高橋 俊幸</a>,<a href="http://d.hatena.ne.jp/keyword/%BA%B4%C6%A3%20%C2%C0%B0%EC" class="keyword">佐藤 太一</a>,<a href="http://d.hatena.ne.jp/keyword/%B3%A4%CC%EE%20%B9%B0%C0%AE" class="keyword">海野 弘成</a>,<a href="http://d.hatena.ne.jp/keyword/%BA%B4%C6%A3%20%CA%E2" class="keyword">佐藤 歩</a>,<a href="http://d.hatena.ne.jp/keyword/%C0%F4%BF%E5%20%E6%C6%B8%E3" class="keyword">泉水 翔吾</a>,<a href="http://d.hatena.ne.jp/keyword/%C5%CF%EE%B4%20%B7%C3%C2%C0" class="keyword">渡邊 恵太</a>,<a href="http://d.hatena.ne.jp/keyword/%B4%DC%CC%EE%20%CD%B4%B0%EC" class="keyword">舘野 祐一</a>,<a href="http://d.hatena.ne.jp/keyword/%C3%E6%C5%E7%20%C1%EF" class="keyword">中島 聡</a>,<a href="http://d.hatena.ne.jp/keyword/%B6%B6%CB%DC%20%E6%C6" class="keyword">橋本 翔</a>,<a href="http://d.hatena.ne.jp/keyword/%A4%CF%A4%DE%A4%C1%A4%E42" class="keyword">はまちや2</a>,<a href="http://d.hatena.ne.jp/keyword/%C3%DD%B8%B6" class="keyword">竹原</a>,<a href="http://d.hatena.ne.jp/keyword/%B0%CB%B2%EC%C9%D2%BC%F9" class="keyword">伊賀敏樹</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%BB%BD%D1%C9%BE%CF%C0%BC%D2">技術評論社</a></li></ul><a href="https://www.amazon.co.jp/dp/4774169552?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>gfx さんのSwift特集。0から勉強する最初のとっかかりに良さそうです。</p>
<h2>Webページ</h2>
<p>Qiita の日本語記事などは日常見てるので、海外のサイトをチョイスしてみました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fwww.objc.io%2Fissue-16%2F" title="Redirecting... · objc.io" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p>人気サイト objc.io の Swift に関する章。「A Warm Welcome to Structs and <a class="keyword" href="http://d.hatena.ne.jp/keyword/Value">Value</a> Types」「Functional APIs with Swift」あたりを重点的に読みたいです。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fnshipster.com%2F" title="NSHipster" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p>同じく人気サイト NSHipster の記事。章としてまとまってはいませんが、サイト右下あたりにまとめてリンクされているようです。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fxavier.hateblo.jp%2Fentry%2F2014%2F06%2F12%2F223346" title="Swift日本語チュートリアル ~ 前編(Apple公式ドキュメントSwift Tour±α) - こんにゃくマガジン" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fxavier.hateblo.jp%2Fentry%2F2014%2F06%2F14%2F201418" title="Swift日本語チュートリアル ~ 後編(Apple公式ドキュメントSwift Tour±α) - こんにゃくマガジン" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a>リファレンスの日本語まとめ記事。サッと確認したくなった時に良さそうです。</p>
<ul>
<li><a href="https://sites.google.com/a/gclue.jp/swift-docs/ni-yinki100-ios">逆引きSwift(iOS編) - Swift Docs</a></li>
</ul>
<p>このサイト知らなかったんですが、機能ごとにとてもまとまってます。興味のある箇所をつまみ読みしていきます。</p>
<h2>ScreenCast</h2>
<p>最近はScreenCastで勉強するのが良いんじゃないかと思ってるんですが、無知のためあまり見つけられず。。良いものをご存知の方いらっしゃれば教えてください!</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fdotinstall.com%2Flessons%2Fbasic_swift" title="【旧版】Swift入門 (全24回) - プログラミングならドットインストール" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p>安定のドットインストール。プレミアム会員限定みたいです。</p>
<ul>
<li><a href="http://nsscreencast.com/episodes">NSScreencast: Bite-sized Screencasts for iOS Development</a></li>
</ul>
<p>こちらは海外のScreenCast。これも有料のようですが、他の動画も面白そうなのでお布施してみようかと思っています。</p>
<h2>ライブラリ</h2>
<p>使うのもそうですが、人気のライブラリのコードを読みたいと思っています。<br />
最近話題にあがったまとめ記事をとりあえずメモ的に。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fdev.classmethod.jp%2Fsmartphone%2Fiphone%2Fswift-oss%2F" title="Swift 時代の新定番!iOS アプリ開発で使えるオススメのオープンソースライブラリまとめ | DevelopersIO" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdeveloper.hatenastaff.com%2Fentry%2F2014%2F12%2F20%2F220721" title="iOS開発で利用しているオープンソースのライブラリやサービスを紹介 - Hatena Developer Blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fqiita.com%2FPGMY%2Fitems%2Fcf2d34e335f03f821f72" title="iOSで気になるライブラリ Swift編 - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<h2>その他 : 2014/12/24 追記</h2>
<p>とても参考になる記事を見つけたのでリンクさせて頂きます。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fqiita.com%2Fyimajo%2Fitems%2F537cd145e62516610131" title="新人iOSプログラマじゃなくても2014年末から正月にかけて読みたい意識高い本(Swiftを中心に) - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fqiita.com%2Fhirokidaichi%2Fitems%2Fd30714f0698dcff1200f" title="新人プログラマに正月休み中を使って読んでみてほしい技術書をセレクトしてみた。 - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<h2>まとめ</h2>
<p>とても年末年始では読み切れなさそうな量になってしまいましたが、<br />
おせち食べながら読みたいと思います。</p>
<p>年明けには読書レポ記事みたいなのを書ければ良いなと思います。</p>
himaratsu
Photos frameworkを使ってiPhoneアルバム内の写真を取得・削除する+α
hatenablog://entry/8454420450073230102
2014-11-11T21:42:52+09:00
2022-02-24T19:50:49+09:00 先日、ALPACAという写真整理アプリを同僚とリリースしました。 ALPACA〜アルパカとカメラロールの画像を削除してアルバムを容量よく整理整頓yuki tanabe仕事効率化無料 iOS 8から追加されたPhotos framworkを使った、アルバムを爆速で整理できるアプリです。その道程で色々と勉強になったので、メモがてらエントリを書いてみます。
<p>先日、<strong>ALPACA</strong>という写真整理アプリを同僚とリリースしました。</p>
<p><div class="itunes-embed freezed itunes-kind-software"><a href="https://apps.apple.com/jp/app/alpaca-%E3%82%A2%E3%83%AB%E3%83%91%E3%82%AB%E3%81%A8%E3%82%AB%E3%83%A1%E3%83%A9%E3%83%AD%E3%83%BC%E3%83%AB%E3%81%AE%E7%94%BB%E5%83%8F%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%A6%E3%82%A2%E3%83%AB%E3%83%90%E3%83%A0%E3%82%92%E5%AE%B9%E9%87%8F%E3%82%88%E3%81%8F%E6%95%B4%E7%90%86%E6%95%B4%E9%A0%93/id934444072?uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank"><img src="https://cdn.image.st-hatena.com/image/scale/a7f1bc745e016ff1ac8d8afe46242dd04c1a69c8/enlarge=0;height=200;version=1;width=200/https%3A%2F%2Fis4-ssl.mzstatic.com%2Fimage%2Fthumb%2FPurple42%2Fv4%2F61%2F07%2Fb1%2F6107b1eb-aeca-a002-9b33-b6e67cfb887c%2Fsource%2F100x100bb.jpg" alt="ALPACA〜アルパカとカメラロールの画像を削除してアルバムを容量よく整理整頓" title="ALPACA〜アルパカとカメラロールの画像を削除してアルバムを容量よく整理整頓" class="itunes-embed-image"/></a><div class="itunes-embed-info"><p class="itunes-embed-title"><a href="https://apps.apple.com/jp/app/alpaca-%E3%82%A2%E3%83%AB%E3%83%91%E3%82%AB%E3%81%A8%E3%82%AB%E3%83%A1%E3%83%A9%E3%83%AD%E3%83%BC%E3%83%AB%E3%81%AE%E7%94%BB%E5%83%8F%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%A6%E3%82%A2%E3%83%AB%E3%83%90%E3%83%A0%E3%82%92%E5%AE%B9%E9%87%8F%E3%82%88%E3%81%8F%E6%95%B4%E7%90%86%E6%95%B4%E9%A0%93/id934444072?uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank">ALPACA〜アルパカとカメラロールの画像を削除してアルバムを容量よく整理整頓</a></p><ul><li class="itunes-embed-artist"><a class="keyword" href="http://d.hatena.ne.jp/keyword/yuki">yuki</a> tanabe</li><li class="itunes-embed-genre">仕事効率化</li><li class="itunes-embed-price">無料</li><li class="itunes-embed-badge"><a href="https://apps.apple.com/jp/app/alpaca-%E3%82%A2%E3%83%AB%E3%83%91%E3%82%AB%E3%81%A8%E3%82%AB%E3%83%A1%E3%83%A9%E3%83%AD%E3%83%BC%E3%83%AB%E3%81%AE%E7%94%BB%E5%83%8F%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%A6%E3%82%A2%E3%83%AB%E3%83%90%E3%83%A0%E3%82%92%E5%AE%B9%E9%87%8F%E3%82%88%E3%81%8F%E6%95%B4%E7%90%86%E6%95%B4%E9%A0%93/id934444072?uo=4&at=10l8JW&ct=hatenablog" rel="nofollow" target="_blank"><img src="https://cdn.blog.st-hatena.com/images/theme/itunes/itunes-badge-appstore@2x.png" width="60px" height="15px" /></a></li></ul></div></div></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8から追加されたPhotos framworkを使った、アルバムを爆速で整理できるアプリです。その道程で色々と勉強になったので、メモがてらエントリを書いてみます。</p>
<h1>Photos frameworkとは</h1>
<p>Photos framework は<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8から新たに追加された<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>です。<br />
Assets Library を置き換えるもので、Aseets Library でできる写真の取得はもちろん、検索や削除などが新たにできるようになりました。</p>
<h1>Photos frameworkを使ってみる</h1>
<p>それでは実装を追っていきます。まずはimportから。</p>
<pre class="code lang-actionscript" data-lang="actionscript" data-unlink><span class="synIdentifier">import</span> Photos
</pre>
<p>以下の変数も定義しておきます。</p>
<pre class="code lang-actionscript" data-lang="actionscript" data-unlink><span class="synStatement">var</span> photoAssets = [PHAsset]()
</pre>
<h2>アルバム内の写真を取得する</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141111/20141111204902.png" alt="f:id:himaratsu:20141111204902p:plain" title="f:id:himaratsu:20141111204902p:plain" class="hatena-fotolife" itemprop="image" width="250"></span><br><span style="color: #979797; font-size: 80%">UIはCollectionViewを使って作っています</span></p>
<p>画像をすべて取得するには以下のように記述します。</p>
<pre class="code lang-actionscript" data-lang="actionscript" data-unlink><span class="synIdentifier">private</span> <span class="synType">func</span> getAllPhotosInfo() {
photoAssets = []
<span class="synComment">// 画像をすべて取得</span>
<span class="synStatement">var</span> assets: PHFetchResult = PHAsset.fetchAssetsWithMediaType(.Image, options: nil)
assets.enumerateObjectsUsingBlock { (asset, <span class="synStatement">index</span>, <span class="synType">stop</span>) -> <span class="synConstant">Void</span> <span class="synStatement">in</span>
self.photoAssets.append(asset as PHAsset)
}
println(photoAssets)
}
</pre>
<p><code>fetchAssetsWithMediaType</code>で欲しいメディアの種類を指定し、リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トします。指定できるタイプは以下の4種類です。</p>
<pre class="code lang-actionscript" data-lang="actionscript" data-unlink>enum PHAssetMediaType : <span class="synStatement">Int</span> {
<span class="synStatement">case</span> <span class="synConstant">Unknown</span>
<span class="synStatement">case</span> Image
<span class="synStatement">case</span> <span class="synStatement">Video</span>
<span class="synStatement">case</span> Audio
}
</pre>
<h3>検索の条件を加える</h3>
<p>日付の範囲を絞ったり、ソートして取得するには<code>PHFetchOptions</code>で指定します。<br />
例えば日時の新しい順に並べるには、以下のようになります:</p>
<pre class="code lang-objc" data-lang="objc" data-unlink>private func <span class="synIdentifier">getAllSortedPhotosInfo</span>() {
photoAssets = []
<span class="synComment">// ソート条件を指定</span>
var options = <span class="synIdentifier">PHFetchOptions</span>()
options.sortDescriptors = [
NSSortDescriptor(key: <span class="synConstant">"creationDate"</span>, ascending: <span class="synConstant">false</span>)
]
var assets: PHFetchResult = PHAsset.<span class="synIdentifier">fetchAssetsWithMediaType</span>(.Image, options: options)
assets.enumerateObjectsUsingBlock { (asset, index, stop) -> Void<span class="synStatement"> in</span>
<span class="synStatement">self</span>.photoAssets.<span class="synIdentifier">append</span>(asset as PHAsset)
}
<span class="synIdentifier">println</span>(photoAssets)
}
</pre>
<p>上記の例では<code>fetchAssetsWithMediaType</code>をコールしてますが、他にも色々なfetchの方法があります。詳しくは公式ドキュメントをご参照ください
<a href="https://developer.apple.com/library/IOs/documentation/Photos/Reference/PHAsset_Class/index.html#//apple_ref/doc/uid/TP40014383-CH1-SW2">https://developer.apple.com/library/IOs/documentation/Photos/Reference/PHAsset_Class/index.html#//apple_ref/doc/uid/TP40014383-CH1-SW2</a></p>
<h2>画像を表示する</h2>
<p>上記で取得した<code>PHAsset</code>をつかって画像を表示してみましょう。</p>
<pre class="code lang-actionscript" data-lang="actionscript" data-unlink>let manager: PHImageManager = PHImageManager()
manager.requestImageForAsset(asset,
targetSize: CGSizeMake(<span class="synConstant">70</span>, <span class="synConstant">70</span>),
contentMode: .AspectFill,
options: nil) { (image, info) -> <span class="synConstant">Void</span> <span class="synStatement">in</span>
<span class="synComment">// 取得したimageをUIImageViewなどで表示する</span>
}
</pre>
<p><code>PHImageManager</code>を使ってリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トし、取得した情報をUIImageViewなどに表示すればOKです。<br />
この resultHandler は場合によって複数回コールされます。大きなサイズの写真を表示するときに時間がかかるため、まずサムネを表示→実際のサイズ表示 と、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>の粋な計らいのようです。これを防ぎたい場合は以下のQiitaが参考になります。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fqiita.com%2Fkaiinui%2Fitems%2Fbdb42d249d3db22dcd56" title="PHImageManager - requestImageForAsset が二回 handler を呼ぶ事案 - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<h2>画像を削除する</h2>
<p>画像を端末から削除するには以下のように実装します。</p>
<pre class="code lang-actionscript" data-lang="actionscript" data-unlink><span class="synIdentifier">private</span> <span class="synType">func</span> deleteFirstImage() {
let delTargetAsset = photoAssets.first as PHAsset?
<span class="synStatement">if</span> delTargetAsset != nil {
PHPhotoLibrary.sharedPhotoLibrary().performChanges(<span class="synError">{</span> () -> <span class="synConstant">Void</span> <span class="synStatement">in</span>
<span class="synComment">// 削除などの変更はこのblocks内でリクエストする</span>
PHAssetChangeRequest.deleteAssets([delTargetAsset!])
<span class="synError">}</span>, completionHandler: <span class="synError">{</span> (success, <span class="synStatement">error</span>) -> <span class="synConstant">Void</span> <span class="synStatement">in</span>
<span class="synComment">// 完了時の処理をここに記述</span>
<span class="synError">}</span>)
}
}
</pre>
<p>削除を実行すると以下のような確認アラートが表示されます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141111/20141111205153.png" alt="f:id:himaratsu:20141111205153p:plain" title="f:id:himaratsu:20141111205153p:plain" class="hatena-fotolife" itemprop="image" width="250px"></span></p>
<p>Delete(日本語環境では「許可」)を選択すると写真が削除されます。</p>
<h3>削除後30日までは復元可</h3>
<p>削除した写真はすぐに消去されず、30日はゴミ箱に残ります。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141111/20141111205257.png" alt="f:id:himaratsu:20141111205257p:plain" title="f:id:himaratsu:20141111205257p:plain" class="hatena-fotolife" itemprop="image" width="250px"></span></p>
<p>上記は「写真」アプリの「アルバム > 最近削除した項目」の画面です。<br />
写真ごとに削除されるまでの日数が表示されており、これが0日になると完全に削除されます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141111/20141111203648.png" alt="f:id:himaratsu:20141111203648p:plain" title="f:id:himaratsu:20141111203648p:plain" class="hatena-fotolife" itemprop="image" width="250px"></span></p>
<p>写真を選択して右上の「Revert」ボタンを押すと上の写真の画面になり、<br />
「Revert 3 photos」を選択すると写真がアルバムに復元されます。</p>
<h2>写真アクセスの許可を取得する</h2>
<h4>許可を求めるシステムアラートを表示する</h4>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141111/20141111205949.png" alt="f:id:himaratsu:20141111205949p:plain" title="f:id:himaratsu:20141111205949p:plain" class="hatena-fotolife" itemprop="image" width="300px"></span></p>
<p>初めて写真を取得する際、<strong>「"あなたのアプリ名"が写真への許可を求めています」</strong> と表示されます。この表示のタイミングを自分でコン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB">トロール</a>するには<code>PHPhotoLibrary.requestAuthorization{...}</code>を呼び出します。詳しくは以下の記事が参考になります。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fdev.classmethod.jp%2Freferences%2Fios8-photo-kit-7%2F" title="[iOS 8] PhotoKit 7 – Photos Framework – フォトライブラリへのアクセス許可を得る | DevelopersIO" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<h4>許可されていない場合は設定画面に遷移させる</h4>
<p>アルバム系アプリや写真加工アプリの場合、写真へのアクセスが拒否されていると困ることが多いかと思います。</p>
<p>その場合はURL <a class="keyword" href="http://d.hatena.ne.jp/keyword/Scheme">Scheme</a>で設定画面へ遷移させ、許可してもらいましょう(<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8以降)。</p>
<pre class="code lang-actionscript" data-lang="actionscript" data-unlink><span class="synComment">// 設定画面へ遷移する</span>
let <span class="synType">url</span> = NSURL(<span class="synStatement">string</span>: UIApplicationOpenSettingsURLString)
UIApplication.sharedApplication().openURL(<span class="synType">url</span>!)
</pre>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141111/20141111211037.png" alt="f:id:himaratsu:20141111211037p:plain" title="f:id:himaratsu:20141111211037p:plain" class="hatena-fotolife" itemprop="image" width="300px"></span></p>
<p>↑こういうアラートを表示するなどして、</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141111/20141111210600.png" alt="f:id:himaratsu:20141111210600p:plain" title="f:id:himaratsu:20141111210600p:plain" class="hatena-fotolife" itemprop="image" width="300px"></span></p>
<p>↑上記のURL <a class="keyword" href="http://d.hatena.ne.jp/keyword/Scheme">Scheme</a>で設定画面へ遷移。</p>
<p>一度「拒否」すると自分で設定画面に辿り着くのは困難ですので、こういう助け舟も用意しておきたいですね。</p>
<p>以上となります。</p>
<h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a></h1>
<p>今回紹介したコードはこちらからDLできます。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fhimaratsu%2FPhotosFrameworkSample" title="GitHub - himaratsu/PhotosFrameworkSample: sample project for photos framework." class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/himaratsu/PhotosFrameworkSample">github.com</a></cite></p>
<h1>まとめ</h1>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8からの新しい<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>「Photos framework」の使い方でした。<br />
これまでより自由度が高くて、いろいろな写真関連のアプリが作れそうですね!</p>
<h1>参考リンク</h1>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fdev.classmethod.jp%2Freferences%2Fios8-photo-kit-1%2F" title="[iOS 8] PhotoKit 1 – Photos frameworkの概要 | DevelopersIO" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe>
<iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fainame.hateblo.jp%2Fentry%2F2014%2F08%2F04%2F084717" title="iOS8のPhotos Kitについてのメモ - ainameの日記" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<h1>おすすめ本</h1>
<p><a href="https://www.amazon.co.jp/exec/obidos/ASIN/4861009499/samura1-22/">[asin:4861009499:detail]</a>
<div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4797380497?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51YLVAWRtSL._SL500_.jpg" class="hatena-asin-detail-image" alt="詳解 Swift" title="詳解 Swift"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4797380497?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">詳解 Swift</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%B2%AE%B8%B6%20%B9%E4%BB%D6" class="keyword">荻原 剛志</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/SB%A5%AF%A5%EA%A5%A8%A5%A4%A5%C6%A5%A3%A5%D6">SBクリエイティブ</a></li></ul><a href="https://www.amazon.co.jp/dp/4797380497?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
himaratsu
iOSアプリでTwitterのタイムライン取得・ツイート投稿を行う(Accounts.frameworkとSocial.rameworkを使って)
hatenablog://entry/8454420450071979599
2014-11-02T22:36:28+09:00
2022-02-24T19:50:49+09:00 iOS 6から Social.framework が登場し、iOSアプリから簡単にツイートできるようになりました。 その方法については以前エントリを書きました。
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 6から Social.framework が登場し、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>アプリから簡単にツイートできるようになりました。 その方法については以前エントリを書きました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fobjc%2Fsnspost" title="画像やURLをFacebookやTwitter、LINEなどのSNSに共有する - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe>
<a href="http://himaratsu.hatenablog.com/entry/objc/snspost">画像やURLをFacebookやTwitter、LINEなどのSNSに共有する - Think Big Act Local</a></p>
<p>上記の記事のやり方では、ポップアップを表示→ツイートする ことしかできません。<br />
例えば <a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a> のクライアントアプリを作りたい場合、独自のUIでツイートを投稿したり、自分のタイムラインを取得したくなるかと思います。</p>
<p>今回は<b><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>端末に登録している<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>アカウント</b>を使って、自由に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>各種にアクセスする方法を紹介します。</p>
<p>(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>全文は<a href="https://gist.github.com/himaratsu/baaa79c8c2926c472ac1">こちら</a>)</p>
<h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を使った<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>アプリの作り方</h1>
<h2>はじめに</h2>
<ul>
<li>UIの話はせず、<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>コールのロジックの話を書きます</li>
<li>Accounts.framework と Social.framework を使います</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>端末に登録している<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>アカウントを使う方法です(下図)</li>
</ul>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141102/20141102214351.png" alt="f:id:himaratsu:20141102214351p:plain" title="f:id:himaratsu:20141102214351p:plain" class="hatena-fotolife" itemprop="image" width="250"></span></p>
<p>ここに登録されている<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>アカウントを使います。</p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>アカウントの取得</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>アカウント取得にAccounts.framework、各種<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>のコールにSocial.frameworkを使います。以下のように準備しておきましょう。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink>import UIKit
import Accounts <span class="synComment">// 追加</span>
import Social <span class="synComment">// 追加</span>
class ViewController: UIViewController {
var accountStore = <span class="synIdentifier">ACAccountStore</span>()
var twAccount: ACAccount?
...
}
</pre>
<p>準備ができたら実際に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>アカウントを取得します。<br />
以下のメソッドを呼ぶとアカウント認証がリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トされます。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink>private func <span class="synIdentifier">selectTwitterAccount</span>() {
<span class="synComment">// 認証するアカウントのタイプを選択(他にはFacebookやWeiboなどがある)</span>
let accountType = accountStore.<span class="synIdentifier">accountTypeWithAccountTypeIdentifier</span>(ACAccountTypeIdentifierTwitter)
accountStore.<span class="synIdentifier">requestAccessToAccountsWithType</span>(accountType, options: <span class="synConstant">nil</span>) { (granted:Bool, error:NSError?) -> Void<span class="synStatement"> in</span>
<span class="synStatement">if</span> error != <span class="synConstant">nil</span> {
<span class="synComment">// エラー処理</span>
<span class="synIdentifier">println</span>(<span class="synConstant">"error! </span><span class="synSpecial">\(</span><span class="synConstant">error)"</span>)
<span class="synStatement">return</span>
}
<span class="synStatement">if</span> !granted {
<span class="synIdentifier">println</span>(<span class="synConstant">"error! Twitterアカウントの利用が許可されていません"</span>)
<span class="synStatement">return</span>
}
let accounts = <span class="synStatement">self</span>.accountStore.<span class="synIdentifier">accountsWithAccountType</span>(accountType) as [ACAccount]
<span class="synStatement">if</span> accounts.count == <span class="synConstant">0</span> {
<span class="synIdentifier">println</span>(<span class="synConstant">"error! 設定画面からアカウントを設定してください"</span>)
<span class="synStatement">return</span>
}
<span class="synComment">// 取得したアカウントで処理を行う...</span>
}
}
</pre>
<p>初めて認証がリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トされた際には、以下のアラートが表示されます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141102/20141102215713.png" alt="f:id:himaratsu:20141102215713p:plain" title="f:id:himaratsu:20141102215713p:plain" class="hatena-fotolife" itemprop="image" width="350"></span></p>
<p>ここで拒否されると次回以降は <code>granted</code> は <code>false</code> となり、アカウント情報にアクセスできません。うまくエラーメッセージを出すなどして、設定画面よりユーザーに許可してもらう必要があります。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8以降では設定画面に遷移するURLスキームが使えますので、利用すると良いと思います。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fqiita.com%2FNight___%2Fitems%2F3d689d657ee691d2cabe" title="iOS8で復活した設定画面へのURLスキーム - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>アカウントを選ぶ</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>アカウントは1つの端末に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%A3%BF%F4%A5%A2%A5%AB%A5%A6%A5%F3%A5%C8">複数アカウント</a>登録できます。<br />
どれか1アカウントだけ利用したい場合は自分で選択させるUIを用意します。</p>
<p>例えば UIAlertController(<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 7以前ではUIActionSheet)で選択させる場合、コードは以下のようになります。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink><span class="synComment">// アカウント選択のActionSheetを表示する</span>
private func <span class="synIdentifier">showAccountSelectSheet</span>(accounts: [ACAccount]) {
let alert = <span class="synIdentifier">UIAlertController</span>(title: <span class="synConstant">"Twitter"</span>,
message: <span class="synConstant">"アカウントを選択してください"</span>,
preferredStyle: .ActionSheet)
<span class="synComment">// アカウント選択のActionSheetを表示するボタン</span>
<span class="synStatement">for</span> account<span class="synStatement"> in </span>accounts {
alert.<span class="synIdentifier">addAction</span>(<span class="synIdentifier">UIAlertAction</span>(title: account.username,
style: .Default,
handler: <span class="synError">{</span> (action) -> Void<span class="synStatement"> in</span>
<span class="synComment">//</span>
<span class="synIdentifier">println</span>(<span class="synConstant">"your select account is </span><span class="synSpecial">\(</span><span class="synConstant">account)"</span>)
<span class="synStatement">self</span>.twAccount = account
}<span class="synError">))</span>
}
<span class="synComment">// キャンセルボタン</span>
alert.<span class="synIdentifier">addAction</span>(<span class="synIdentifier">UIAlertAction</span>(title: <span class="synConstant">"Cancel"</span>, style: .Cancel, handler: <span class="synConstant">nil</span>))
<span class="synComment">// 表示する</span>
<span class="synStatement">self</span>.<span class="synIdentifier">presentViewController</span>(alert, animated: <span class="synConstant">true</span>, completion: <span class="synConstant">nil</span>)
}
</pre>
<p>実行すると以下のように表示されるかと思います。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141102/20141102222704.png" alt="f:id:himaratsu:20141102222704p:plain" title="f:id:himaratsu:20141102222704p:plain" class="hatena-fotolife" itemprop="image" width="350"></span></p>
<p>AlertController で選択されたアカウントは<code>twAccount</code>という変数に保持されます。<br />
以後はこの情報を使って<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>コールすることになります。</p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>をたたく</h2>
<h3>タイムラインの取得</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>のタイムラインを取得するコードは以下になります。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink><span class="synComment">// タイムラインを取得する</span>
private func <span class="synIdentifier">getTimeline</span>() {
let URL = <span class="synIdentifier">NSURL</span>(string: <span class="synConstant">"https://api.twitter.com/1.1/statuses/user_timeline.json"</span>)
<span class="synComment">// GET/POSTやパラメータに気をつけてリクエスト情報を生成</span>
let request = <span class="synIdentifier">SLRequest</span>(forServiceType: SLServiceTypeTwitter,
requestMethod: .GET,
URL: URL,
parameters: <span class="synConstant">nil</span>)
<span class="synComment">// 認証したアカウントをセット</span>
request.account = twAccount
<span class="synComment">// APIコールを実行</span>
request.performRequestWithHandler { (responseData, urlResponse, error) -> Void<span class="synStatement"> in</span>
<span class="synStatement">if</span> error != <span class="synConstant">nil</span> {
<span class="synIdentifier">println</span>(<span class="synConstant">"error is </span><span class="synSpecial">\(</span><span class="synConstant">error)"</span>)
}
<span class="synStatement">else</span> {
<span class="synComment">// 結果の表示</span>
let result = NSJSONSerialization.<span class="synIdentifier">JSONObjectWithData</span>(responseData,
options: .AllowFragments,
error: <span class="synConstant">nil</span>)
as NSArray
<span class="synIdentifier">println</span>(<span class="synConstant">"result is </span><span class="synSpecial">\(</span><span class="synConstant">result)"</span>)
}
}
}
</pre>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の仕様については<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a> の <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> リファレンスを見て確認します。<br />
タイムラインの取得だと以下のページになります。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdev.twitter.com%2Frest%2Freference%2Fget%2Fstatuses%2Fuser_timeline" title="API reference index" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p>成功すればタイムラインを流れるツイート情報が取得できたかと思います。</p>
<h3>新しいツイートの投稿</h3>
<p>ツイートを投稿する場合は以下のコードになります。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink><span class="synComment">// ツイートを投稿</span>
private func <span class="synIdentifier">postTweet</span>() {
let URL = <span class="synIdentifier">NSURL</span>(string: <span class="synConstant">"https://api.twitter.com/1.1/statuses/update.json"</span>)
<span class="synComment">// ツイートしたい文章をセット</span>
let params = [<span class="synConstant">"status"</span> : <span class="synConstant">"Tweet from iOS!"</span>]
<span class="synComment">// リクエストを生成</span>
let request = <span class="synIdentifier">SLRequest</span>(forServiceType: SLServiceTypeTwitter,
requestMethod: .POST,
URL: URL,
parameters: params)
<span class="synComment">// 取得したアカウントをセット</span>
request.account = twAccount
<span class="synComment">// APIコールを実行</span>
request.performRequestWithHandler { (responseData, urlResponse, error) -> Void<span class="synStatement"> in</span>
<span class="synStatement">if</span> error != <span class="synConstant">nil</span> {
<span class="synIdentifier">println</span>(<span class="synConstant">"error is </span><span class="synSpecial">\(</span><span class="synConstant">error)"</span>)
}
<span class="synStatement">else</span> {
<span class="synComment">// 結果の表示</span>
let result = NSJSONSerialization.<span class="synIdentifier">JSONObjectWithData</span>(responseData, options: .AllowFragments, error: <span class="synConstant">nil</span>) as NSDictionary
<span class="synIdentifier">println</span>(<span class="synConstant">"result is </span><span class="synSpecial">\(</span><span class="synConstant">result)"</span>)
}
}
}
</pre>
<p>認証したアカウントを確認してみましょう。成功すれば以下のように投稿されていると思います。</p>
<blockquote class="twitter-tweet" lang="ja"><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Tweet">Tweet</a> from <a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>!</p>— ほんとは超いそがし松 (@himara2) <a href="https://twitter.com/himara2/status/528883263004094465">2014, 11月 2</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>無事ツイートできているのが確認できました!</p>
<h3>他の<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>をコールするには</h3>
<p>他の<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>も上記と同様にコールできます。<a href="https://dev.twitter.com/rest/public">公式のAPIリファレンス</a>を確認しながら利用しましょう。</p>
<p>日本語だと、以下のようなページもあるようです。</p>
<p><a href="http://dx.24-7.co.jp/twitterapi1-1-rest-api/">http://dx.24-7.co.jp/twitterapi1-1-rest-api/</a></p>
<p><a href="http://dx.24-7.co.jp/twitterapi1-1-rest-api/">http://dx.24-7.co.jp/twitterapi1-1-rest-api/</a></p>
<h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>全文</h1>
<p>このエントリの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>はGistにすべて貼っています。<br />
<a href="https://gist.github.com/himaratsu/baaa79c8c2926c472ac1">https://gist.github.com/himaratsu/baaa79c8c2926c472ac1</a></p>
<h1>まとめ</h1>
<p>自前でUIを用意できるので、自分のサービスに投稿すると同時に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>にポストする場合などに使えますね。<br />
最近<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を利用するアプリを書く機会が多いのですが、いつも忘れるのでメモでした。</p>
<h1>参考リンク</h1>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fqiita.com%2Fpaming%2Fitems%2F9a6b51fa56915d1f1d64" title="3周遅れぐらいでiOSのSocial.frameworkを使ってみる - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe>
<iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fobjc%2Fsnspost" title="画像やURLをFacebookやTwitter、LINEなどのSNSに共有する - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<h1>関連書籍</h1>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4861009499?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51WHtltDWLL._SL500_.jpg" class="hatena-asin-detail-image" alt="たのしいSwiftプログラミング―[iOS 8&Xcode 6対応]" title="たのしいSwiftプログラミング―[iOS 8&Xcode 6対応]"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4861009499?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">たのしいSwiftプログラミング―[iOS 8&Xcode 6対応]</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%CC%DA%B2%BC%20%C0%BF" class="keyword">木下 誠</a></li><li>ビー・エヌ・エヌ新社</li></ul><a href="https://www.amazon.co.jp/dp/4861009499?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4844334476?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51omKgN0AsL._SL500_.jpg" class="hatena-asin-detail-image" alt="RailsとiPhoneではじめるアプリケーション開発" title="RailsとiPhoneではじめるアプリケーション開発"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4844334476?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">RailsとiPhoneではじめるアプリケーション開発</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%B7%AA%C5%C4%20%CD%B3%BA%DA" class="keyword">栗田 由菜</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%D7%A5%EC%A5%B9">インプレス</a></li></ul><a href="https://www.amazon.co.jp/dp/4844334476?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
himaratsu
GitHub Pages でWebサイトをホスティングする(独自ドメイン使用)
hatenablog://entry/8454420450068384121
2014-10-16T21:36:43+09:00
2022-02-24T19:50:56+09:00 最近、iOS.zipというWebサイトのホスティングをGitHub Pages運用に変更しました。 簡単に設定できてしかも無料ということで今後も使う機会は多くなりそうです。 後で見返すときのために、設定の手順を記録しておきます。 (2014/10/16 現在の手順です)
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141008/20141008181608.png" alt="f:id:himaratsu:20141008181608p:plain" title="f:id:himaratsu:20141008181608p:plain" class="hatena-fotolife" itemprop="image" style="border:1px solid #ccc"></span></p>
<p>最近、<a href="http://ioszip.mashroom.in/">iOS.zipというWebサイト</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DB%A5%B9%A5%C6%A5%A3%A5%F3%A5%B0">ホスティング</a>を<a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a> Pages運用に変更しました。<br />
簡単に設定できてしかも無料ということで今後も使う機会は多くなりそうです。</p>
<p>後で見返すときのために、設定の手順を記録しておきます。<br />
(2014/10/16 現在の手順です)</p>
<h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a> Pagesって?</h1>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>から直接<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DB%A5%B9%A5%C6%A5%A3%A5%F3%A5%B0">ホスティング</a>できるサービスです。<br />
裏で<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>とかが動かない、静的なページを簡単に構築することができます。</p>
<p>公式の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>は以下です。とても詳細に作られています。</p>
<ul>
<li><a href="https://pages.github.com/">https://pages.github.com/</a></li>
</ul>
<p>こちらを参考に設定をすすめたメモを書いていきます。</p>
<h1>やったこと</h1>
<ol>
<li>ioszip というOrganizationを作成</li>
<li><a href="https://github.com/ioszip/ioszip.github.io">ioszip/ioszip.github.io</a> という<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>を作成(ここで<a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a> Pagesを使う)</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a> Pagesの設定</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C6%C8%BC%AB%A5%C9%A5%E1%A5%A4%A5%F3">独自ドメイン</a>を設定</li>
</ol>
<h2>1.ioszip というOrganizationを作成</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141013/20141013034411.png" alt="f:id:himaratsu:20141013034411p:plain" title="f:id:himaratsu:20141013034411p:plain" class="hatena-fotolife" itemprop="image" width="300" style="border: 1px solid #ccc"></span></p>
<p>↑の画像の一番下の「Create organization」から作成します。<br />
名前はなんでも良いですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>.zipの場合は<code>ioszip</code>にしています。</p>
<h2>2. ioszip/ioszip.<a class="keyword" href="http://d.hatena.ne.jp/keyword/github">github</a>.io という<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>を作成</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141013/20141013041444.png" alt="f:id:himaratsu:20141013041444p:plain" title="f:id:himaratsu:20141013041444p:plain" class="hatena-fotolife" itemprop="image" style="border: 1px solid #ccc" width="400"></span></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>名を <code>{organization_name}.github.io</code> として<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>を作成します。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>.zipの場合は ioszip.<a class="keyword" href="http://d.hatena.ne.jp/keyword/github">github</a>.io という名前で作ることになります。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>が作成できたら、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DB%A5%B9%A5%C6%A5%A3%A5%F3%A5%B0">ホスティング</a>させたいファイル群をpushします。ルートは<code>index.html</code>になります。</p>
<h2>3. <a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a> Pagesの設定</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>の設定の下側に「<a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a> Pages」という項目があります。ここで表示用URLを確認します。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141013/20141013034915.png" alt="f:id:himaratsu:20141013034915p:plain" title="f:id:himaratsu:20141013034915p:plain" class="hatena-fotolife" itemprop="image" style="border: 1px solid #ccc"></span></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>を設定しているためカスタム<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>( <a href="http://ioszip.mashroom.in">http://ioszip.mashroom.in</a> )となっていますが、ここにはおそらく http://{organization_name}.<a class="keyword" href="http://d.hatena.ne.jp/keyword/github">github</a>.io のようなURLが表示されているはずです。</p>
<p>表示されているURLに早速アクセスしてみると、</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141013/20141013035107.png" alt="f:id:himaratsu:20141013035107p:plain" title="f:id:himaratsu:20141013035107p:plain" class="hatena-fotolife" itemprop="image" style="border: 1px solid #ccc"></span></p>
<p>上記のような404ページが表示されてしまうと思います。<br />
pushしてから反映まで5-10分ほどかかるようですので、少し待ちましょう。</p>
<h2>4.<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C6%C8%BC%AB%A5%C9%A5%E1%A5%A4%A5%F3">独自ドメイン</a>を設定</h2>
<p>さて、表示の確認ができたらカスタム<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>を設定します。<br />
今回は、<code>http://ioszip.github.io</code>にアクセスしたら<code>http://ioszip.mashroom.in</code>を表示するように設定します。</p>
<h3>4-1.<a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a>側の設定</h3>
<p>お名前.comや<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E0%A1%BC%A5%E0%A1%BC%A5%C9%A5%E1%A5%A4%A5%F3">ムームードメイン</a>など、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C6%C8%BC%AB%A5%C9%A5%E1%A5%A4%A5%F3">独自ドメイン</a>を取得した側での設定です。<br />
CNAMEを選択し、値を記述する箇所に手順3で確認した表示用URLを入力します。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>.zip の場合は <code>ioszip.github.io</code> を入力しました。</p>
<p>自分の場合は <a href="https://dozens.jp/">Dozens.jp</a> を使って設定したのですが、そのときの画面がこちらです。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141013/20141013040508.png" alt="f:id:himaratsu:20141013040508p:plain" title="f:id:himaratsu:20141013040508p:plain" class="hatena-fotolife" itemprop="image" style="border: 1px solid #ccc" width="400"></span></p>
<p>Dozens(ダズンズ)は読みにくいですがとても使いやすいサービスだと思います。</p>
<p><a href="https://dozens.jp/">https://dozens.jp/</a></p>
<p><a href="https://dozens.jp/">https://dozens.jp/</a></p>
<h3>4-2.<a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a> Pages側</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a> Pages 側の設定です。
こちらは簡単で、<code>CNAME</code>というファイルを作成し、元のURLを記述してpushします。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>.zip の場合は <code>ioszip.mashroom.in</code>とだけ書かれたCNAMEという名前のファイルを作りました。実物はこちらになります:
<a href="https://github.com/ioszip/ioszip.github.io/blob/master/CNAME">https://github.com/ioszip/ioszip.github.io/blob/master/CNAME</a></p>
<h3>4-3.少し待つ</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a>の設定が反映されるまでには少し時間がかかります。<br />
少し時間をおいてから反映されたことを確認しましょう。</p>
<h1>まとめ</h1>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a> Pages でWebサイトを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DB%A5%B9%A5%C6%A5%A3%A5%F3%A5%B0">ホスティング</a>する方法についてのまとめでした。<br />
アプリのランディングページ等の用途にはこの方法で十分対応できそうです。</p>
<p>バックエンドを伴った動的なサービスもHerokuで作れてしまいますし、とりあえずサーバーを持たずに出来ることがとても増えていて助かりますね。</p>
<h2>おまけ</h2>
<p>今回題材となった<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>.zipはこちらからご利用頂けます。</p>
<p><a href="http://ioszip.mashroom.in/">iOS.zip | iOSアプリ申請に必要な素材を1clickで用意</a></p>
<h1>関連リンク</h1>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a>公式のカスタム<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>設定方法
<ul>
<li><a href="https://help.github.com/articles/setting-up-a-custom-domain-with-github-pages/">Configuring a custom domain for your GitHub Pages site - GitHub Docs</a></li>
</ul>
</li>
<li><a href="http://blog.awairo.net/blog/2013/12/14/custom-domain-for-gh-pages/">GitHub Pagesで独自ドメインを使う方法 - AwAlog</a></li>
</ul>
<h1>関連書籍</h1>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/477416366X?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51PjpAUHZBL._SL500_.jpg" class="hatena-asin-detail-image" alt="GitHub実践入門 ~Pull Requestによる開発の変革 (WEB+DB PRESS plus)" title="GitHub実践入門 ~Pull Requestによる開発の変革 (WEB+DB PRESS plus)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/477416366X?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">GitHub実践入門 ~Pull Requestによる開発の変革 (WEB+DB PRESS plus)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C2%E7%C4%CD%20%B9%B0%B5%AD" class="keyword">大塚 弘記</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%BB%BD%D1%C9%BE%CF%C0%BC%D2">技術評論社</a></li></ul><a href="https://www.amazon.co.jp/dp/477416366X?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4048915134?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51GpKqXfUrL._SL500_.jpg" class="hatena-asin-detail-image" alt="プロフェッショナルのための 実践Heroku入門 プラットフォーム・クラウドを活用したアプリケーション開発と運用 (書籍)" title="プロフェッショナルのための 実践Heroku入門 プラットフォーム・クラウドを活用したアプリケーション開発と運用 (書籍)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4048915134?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">プロフェッショナルのための 実践Heroku入門 プラットフォーム・クラウドを活用したアプリケーション開発と運用 (書籍)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C1%EA%DF%B7%CA%E2" class="keyword">相澤歩</a>,<a href="http://d.hatena.ne.jp/keyword/arton" class="keyword">arton</a>,<a href="http://d.hatena.ne.jp/keyword/%C4%BB%B0%E6%C0%E3" class="keyword">鳥井雪</a>,<a href="http://d.hatena.ne.jp/keyword/%BF%A5%C5%C4%B7%C9%BB%D2" class="keyword">織田敬子</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/KADOKAWA">KADOKAWA</a>/<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B9%A5%AD%A1%BC%A1%A6%A5%E1%A5%C7%A5%A3%A5%A2%A5%EF%A1%BC%A5%AF%A5%B9">アスキー・メディアワークス</a></li></ul><a href="https://www.amazon.co.jp/dp/4048915134?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
himaratsu
iOS.zipのコマンドラインツール ioszip をリリースしました
hatenablog://entry/8454420450068369231
2014-10-12T22:39:49+09:00
2022-02-24T19:50:49+09:00 iOS.zip のコマンドラインツールができました。 Webサイトを開くことなく、1コマンドでzipファイルがダウンロードできます。
<p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://ioszip.mashroom.in" target="_blank"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141012/20141012214714.png" alt="f:id:himaratsu:20141012214714p:plain" title="f:id:himaratsu:20141012214714p:plain" class="hatena-fotolife" itemprop="image" style="border:1px solid #ccc"></a></span></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>.zip の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%E9%A5%A4%A5%F3">コマンドライン</a>ツールができました。<br />
Webサイトを開くことなく、1コマンドでzipファイルがダウンロードできます。</p>
<p><a href="http://ioszip.mashroom.in/"><b>iOS.zip</b></a> は1クリックで<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>アプリの申請に必要な画像が分かるサイトです。</p>
<h1>セットアップと使い方</h1>
<p>Homebrewを使って簡単に利用できます。Homebrewが入ってない方はこちらの記事などを参考に準備してください。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fqiita.com%2Fis0me%2Fitems%2F475fdbc4d770534f9ef1" title="MacにHomebrewをインストールする - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<h3>Install(Homebrewを使って)</h3>
<pre class="code bash" data-lang="bash" data-unlink>$ brew tap ioszip/ioszip
$ brew install ioszip</pre>
<p>上記のコマンドで <code>ioszip</code> コマンドがインストールされます。</p>
<h3>Usage</h3>
<pre class="code bash" data-lang="bash" data-unlink>$ ioszip download</pre>
<p>上記のコマンドでカレント<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リにzipファイルがダウンロードされます。</p>
<h1>Pull Request から生まれたツール</h1>
<p><a href="https://github.com/ioszip/ioszip.github.io/pull/1">CUIで使えるioszipコマンドを用意した by shoma2da · Pull Request #1 · ioszip/ioszip.github.io · GitHub</a></p>
<p><span itemscope itemtype="http://schema.org/Photograph"><a href="https://github.com/ioszip/ioszip.github.io/pull/1" target="_blank"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141012/20141012215454.png" alt="f:id:himaratsu:20141012215454p:plain" title="f:id:himaratsu:20141012215454p:plain" class="hatena-fotolife" itemprop="image" style="border: 1px solid #ccc"></a></span></p>
<p><a href="http://blog.hatena.ne.jp/shoma2da/">id:shoma2da</a> くんにプルリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トをもらって出来た<a class="keyword" href="http://d.hatena.ne.jp/keyword/CUI">CUI</a>ツールです。ありがとうございます!</p>
<p>ほとんど作ってもらった形で、僕がやったことはプルリをMergeしたこと、以下の手順でHomebrew対応したことの2点です。</p>
<ul>
<li><a href="https://github.com/ioszip/homebrew-ioszip">Homebrew 用のリポジトリ</a>を準備</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%A7%A5%EB%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">シェルスクリプト</a>やヘルプ用のファイルを配置</li>
</ul>
<p>Homebrew対応は初めてでしたが、以下の記事を参考にさせて頂き、特に詰まることなく設定できました。</p>
<ul>
<li><a href="http://blog.monochromegane.com/blog/2014/05/19/homebrew-formula-for-golang/">Go言語でつくったツールをHomebrewで配布する · THINKING MEGANE</a></li>
<li><a href="http://deeeet.com/writing/2014/05/20/brew-tap/">HomeBrewで自作ツールを配布する | SOTA</a></li>
</ul>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/CUI">CUI</a>ツール作りたい欲</h2>
<p>あまり関係ないですが<a class="keyword" href="http://d.hatena.ne.jp/keyword/YAPC">YAPC</a>の以下のスライドを見て以来、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CUI">CUI</a>ツール作りたい欲があがってます。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fyapcasia.org%2F2014%2Ftalk%2Fshow%2Fb49cc53a-027b-11e4-9357-07b16aeab6a4" title="コマンドラインツールについて語るときに僕の語ること - YAPC::Asia Tokyo 2014" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p><a href="http://yapcasia.org/2014/talk/show/b49cc53a-027b-11e4-9357-07b16aeab6a4">コマンドラインツールについて語るときに僕の語ること - YAPC::Asia Tokyo 2014</a></p>
<p>今回のプルリで何となく仕組みがなんとなく分かってきたので、自分でも何か作ってみたいですね。</p>
<h1>まとめ</h1>
<p>Webサイトも<a class="keyword" href="http://d.hatena.ne.jp/keyword/CUI">CUI</a>ツールの追加にあわせて更新しています。<br />
<a href="http://ioszip.mashroom.in/#cui">iOS.zip | iOSアプリ申請に必要な素材を1clickで用意</a></p>
<p>これまで以上に簡単になった<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>.zip、ぜひご利用ください!</p>
<h1>関連リンク</h1>
<p><a href="http://deeeet.com/writing/2014/08/27/cli-reference/">コマンドラインツールを作るときに参考にしている資料 | Taichi Nakashima</a>
<a href="https://www.amazon.co.jp/exec/obidos/ASIN/B00J4KDYV4/samura1-22/">[asin:B00J4KDYV4:detail]</a>
<a href="https://www.amazon.co.jp/exec/obidos/ASIN/4774146439/samura1-22/">[asin:4774146439:detail]</a></p>
himaratsu
iOS.zipにiPhone 6/iPhone 6 plus用のサイズを追加したけどあまり意味がなかった話
hatenablog://entry/8454420450067989622
2014-10-08T18:37:18+09:00
2022-02-24T19:50:53+09:00 1年ほど前、iOS.zipというWebサイトを作りました。 iOSアプリの申請に必要なサイズのダミー画像がzipでダウンロードできるサイトです。 このzipファイルにiPhone 6/iPhone 6 Plus用サイズの画像を追加しました。
<p><a href="http://ioszip.mashroom.in"><p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141008/20141008181608.png" alt="f:id:himaratsu:20141008181608p:plain" title="f:id:himaratsu:20141008181608p:plain" class="hatena-fotolife" itemprop="image" width="500" style="border:1px solid #ccc"></span></p></a></p>
<p>1年ほど前、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>.zipというWebサイトを作りました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fioszip" title="iOS.zip というサイトをつくりました - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p><b><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>アプリの申請に必要なサイズのダミー画像がzipでダウンロードできる</b>サイトです。<br />
このzipファイルに<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone%206">iPhone 6</a>/<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone%206%20Plus">iPhone 6 Plus</a>用サイズの画像を追加しました。</p>
<p><u><a href="http://ioszip.mashroom.in/">iOS.zip | iOSアプリ申請に必要な素材を1clickで用意</a></u></p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>.zipをつくった経緯</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141008/20141008182206.png" alt="f:id:himaratsu:20141008182206p:plain" title="f:id:himaratsu:20141008182206p:plain" class="hatena-fotolife" itemprop="image" width="250" style="border: 1px solid #ccc"></span></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iTunes">iTunes</a> Connect上でアプリを作成するには、<b>1024x1024アイコン</b>、<b>各画面サイズの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A1%BC%A5%F3%A5%B7%A5%E7%A5%C3%A5%C8">スクリーンショット</a>画像</b>が先に必要です。</p>
<p>これが揃っていないと新規に作成したアプリを保存できません。しかし上記がない状態で先に一時的なアプリを作っておきたい場合があります。例えば以下の場合です:</p>
<ul>
<li>新規アプリのリリースで、スクショまだないけど description を書き始めたい</li>
<li>Game Center や In-App Purchase のテスト用にアプリを作りたい</li>
</ul>
<p>適当な画像を用意するのも地味に大変。それじゃあ必要な画像(のダミー画像)を一括でDLできたらちょっと便利じゃない?という思いで作りました。</p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/iTunes">iTunes</a> Connect、画像なしでもアプリを作れるようになってました</h2>
<p>「あまり意味がなかった」とタイトルに付けています。なんと<a class="keyword" href="http://d.hatena.ne.jp/keyword/iTunes">iTunes</a> Connect、画像なしでもアプリを作成できるようになっていました。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141008/20141008175642.png" alt="f:id:himaratsu:20141008175642p:plain" title="f:id:himaratsu:20141008175642p:plain" class="hatena-fotolife" itemprop="image" style="border: 1px solid #ccc"></span></p>
<p>この変更により<a class="keyword" href="http://d.hatena.ne.jp/keyword/iTunes">iTunes</a> Connect上で爆速でアプリを作れるようになりました。細かな仕様変更ですが助かりますね。</p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>.zipに<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone%206">iPhone 6</a>/<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone%206%20Plus">iPhone 6 Plus</a>用サイズを追加しました</h2>
<p>さて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>.zipですが、上記の変更に気づかず<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone%206">iPhone 6</a>/<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone%206%20Plus">iPhone 6 Plus</a>対応をやりました!</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20141008/20141008181608.png" alt="f:id:himaratsu:20141008181608p:plain" title="f:id:himaratsu:20141008181608p:plain" class="hatena-fotolife" itemprop="image" width="500" style="border:1px solid #ccc"></span></p>
<p><a href="http://ioszip.mashroom.in/">iOS.zip | iOSアプリ申請に必要な素材を1clickで用意</a></p>
<p>サイトにある<b>「Download <a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>.zip」</b>をクリックすると画像が詰まったzipファイルがDLできます。申請に必要なサイズを確認したい際などにお使いいただければと思います。</p>
<h2>まとめ</h2>
<p>引き続き <a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>.zip をよろしくお願いいたします。</p>
<p><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B00JNTZ89W/samura1-22/">[asin:B00JNTZ89W:detail]</a> <div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4774163856?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51UFj4B6NOL._SL500_.jpg" class="hatena-asin-detail-image" alt="iOSアプリエンジニア養成読本[クリエイティブな開発のための技術力/デザイン力/マインドを養う! ] (Software Design plus)" title="iOSアプリエンジニア養成読本[クリエイティブな開発のための技術力/デザイン力/マインドを養う! ] (Software Design plus)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4774163856?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">iOSアプリエンジニア養成読本[クリエイティブな開発のための技術力/デザイン力/マインドを養う! ] (Software Design plus)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%B9%E2%B6%B6%20%BD%D3%B8%F7" class="keyword">高橋 俊光</a>,<a href="http://d.hatena.ne.jp/keyword/%BF%DB%CB%AC%20%CD%AA%B5%AA" class="keyword">諏訪 悠紀</a>,<a href="http://d.hatena.ne.jp/keyword/%C5%F2%C2%BC%20%CD%E3" class="keyword">湯村 翼</a>,<a href="http://d.hatena.ne.jp/keyword/%CA%BF%B2%B0%20%BF%BF%B8%E3" class="keyword">平屋 真吾</a>,<a href="http://d.hatena.ne.jp/keyword/%CA%BF%B0%E6%20%CD%B4%BC%F9" class="keyword">平井 祐樹</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%BB%BD%D1%C9%BE%CF%C0%BC%D2">技術評論社</a></li></ul><a href="https://www.amazon.co.jp/dp/4774163856?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
himaratsu
第9回はFablic開催! #potatotips で発表されたiOSのtipsまとめ
hatenablog://entry/12921228815733545324
2014-09-25T00:17:21+09:00
2022-02-24T19:50:49+09:00 第9回となる #potatotips に参加させて頂きました。 今回は話題のフリマアプリFrillを作っているFablic社@恵比寿での開催でした。 https://github.com/potatotips/potatotips/wiki/Potatotips-9
<p>第9回となる #potatotips に参加させて頂きました。<br />
今回は<a href="https://fablic.co.jp/">話題のフリマアプリFrillを作っているFablic社</a>@恵比寿での開催でした。
<a href="https://github.com/potatotips/potatotips/wiki/Potatotips-9">https://github.com/potatotips/potatotips/wiki/Potatotips-9</a></p>
<blockquote class="twitter-tweet" lang="ja"><p>Fablicさんにお邪魔してきました <a href="https://twitter.com/hashtag/potatotips?src=hash">#potatotips</a> <a href="http://t.co/YwcySl0Y2v">pic.twitter.com/YwcySl0Y2v</a></p>— ほんとは超いそがし松 (@himara2) <a href="https://twitter.com/himara2/status/514791253783748608">2014, 9月 24</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>potatotipsは基本的に発表者だけが参加できる、持ち時間1人5分のtips共有会です。<br />
9回目となる今回は<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8が出た初の開催ということもあり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8のtipsが多い会となりました。</p>
<p>そんな第9回で発表された7個の<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>のtipsをまとめます!</p>
<h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> tips</h1>
<h3>App ExtensionでCocoaPods管理しているライブラリを使用する方法</h3>
<ul>
<li><a href="https://twitter.com/tomonobu_sato">@tomonobu_sato</a>さん</li>
<li>CocoaPodsをExtensionやEmbeded Frameworkで使いたい</li>
<li><code>target</code>を使う方法と<code>link_with</code>を使う方法について</li>
<li><script async class="speakerdeck-embed" data-id="6701fa30260c01321bc24ae0e5b5fdf3" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
<li><a href="https://github.com/tmnb/TodayExtensionSample-Framework">サンプルコード | GitHub</a></li>
</ul>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>の現場で訊いてきたTips</h3>
<ul>
<li><a href="https://twitter.com/yimajo">@yimajo</a> さん</li>
<li>各社をインタビューして回って得た知見の発表</li>
<li>記事にしなかったtips
<ul>
<li><a href="https://itunes.apple.com/jp/app/sip/id507257563?mt=12">Mac OS X 向けカラーピッカーアプリ「sip」</a></li>
<li>User-defined Macro で<code>BUNDLER_IDENTIFIER</code>を定義してBundleIDを出し分け</li>
<li>ユーザーテスト、不具合の発見に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BB%A5%F3%A5%C6%A5%A3%A5%D6">インセンティブ</a>与えると良い</li>
<li>BlocksKitはデメリットも多いので注意</li>
</ul>
</li>
<li>過去のインタビュー記事はこちら
<ul>
<li><a href="http://qiita.com/yimajo/items/bb75fb91c0d48a6d2196">iOSアプリ開発の現場で訊いてみた!ユビレジ編</a></li>
<li><a href="http://qiita.com/yimajo/items/26c8e29e44a34a683a78">iOSアプリ開発の現場で訊いてみた!フリル編</a></li>
</ul>
</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/39479533" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/YoshinoriImajo/iostips-39479533" title="iOSアプリ開発の現場で訊いてきたtips" target="_blank">iOSアプリ開発の現場で訊いてきたtips</a> </strong> from <strong><a href="http://www.slideshare.net/YoshinoriImajo" target="_blank">今城 善矩</a></strong> </div></li>
<li>インタビューを受けても良いという企業は @yimajo さんまで</li>
</ul>
<h3>SioriでどのようにCustom Transitionを実装しているか</h3>
<ul>
<li><a href="https://twitter.com/ferasyasin">@ferasyasin</a> さん</li>
<li>Custom Transitionについて</li>
<li>Custom Transitionを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A5%E9%A5%AF%A5%C6%A5%A3%A5%D6">インタラクティブ</a>にする</li>
<li>複数のgestureRecognizerを制御する</li>
<li><script async class="speakerdeck-embed" data-id="c74cb4e026060132644d4a087780ba60" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
<li>説明されたSioriのアプリはこちら
<ul>
<li><a href="https://itunes.apple.com/us/app/wired-vicenadono-hao-qi-xinwo/id913849903?mt=8">https://itunes.apple.com/us/app/wired-vicenadono-hao-qi-xinwo/id913849903?mt=8</a></li>
</ul>
</li>
</ul>
<h3>Interface BuilderでカスタムViewの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%F3%A5%C0%A5%EA%A5%F3%A5%B0">レンダリング</a></h3>
<ul>
<li><a href="https://twitter.com/hayashi311">@hayashi311</a> さん</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> 6からCustom Viewのライブ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%F3%A5%C0%A5%EA%A5%F3%A5%B0">レンダリング</a>が可能に</li>
<li>IB_DESIGNABLE
<ul>
<li>カスタムViewがInterface Builder上に反映される</li>
</ul>
</li>
<li>IBInspectable
<ul>
<li>カスタムのプロパティもInterface Buidler上から入力できる</li>
</ul>
</li>
<li>動きをみると裏でSimulatorを立ち上げてキャプチャを撮って反映させている</li>
<li><script async class="speakerdeck-embed" data-id="ee32ed40262f0132644f4a087780ba60" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8での画像処理 + α</h3>
<ul>
<li><a href="https://twitter.com/_shingt">@_shingt</a>さん</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Core%20Image">Core Image</a>を使った画像処理について</li>
<li>CIKernelの中身を書いて自作のCIFilterを作る</li>
<li>MotionBlur を使って移動時にエフェクトをかるとカッコイイ
<ul>
<li><a href="https://github.com/fastred/MotionBlur">GitHub - fastred/MotionBlur: MotionBlur allows you to add motion blur effect to iOS animations.</a></li>
</ul>
</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/39478053" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/shinenshin1/ios8-39478053" title="iOS8での画像処理+α" target="_blank">iOS8での画像処理+α</a> </strong> from <strong><a href="http://www.slideshare.net/shinenshin1" target="_blank">Shinichi Goto</a></strong> </div></li>
</ul>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>におけるUIテスト</h3>
<ul>
<li><a href="https://twitter.com/kitasuke">@kitasuke</a>さん</li>
<li>KIFを使った<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>のUIテストを紹介
<ul>
<li>KIFはSquareが作ったUIテスト用の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a></li>
</ul>
</li>
<li>KIFでできること・KIFの使い方</li>
<li>KIF+Screenshot撮影 => テスト結果を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A1%BC%A5%F3%A5%B7%A5%E7%A5%C3%A5%C8">スクリーンショット</a>で確認できる</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/ImageMagick">ImageMagick</a> montageで合成, compositeでdiffをとってテストをできるだけ自動化する</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/39470814" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/kitasuke/iosui" title="iOSにおけるUIテスト@potetotips" target="_blank">iOSにおけるUIテスト@potetotips</a> </strong> from <strong><a href="http://www.slideshare.net/kitasuke" target="_blank">Yusuke Kita</a></strong> </div></li>
</ul>
<h3>Let's Build Custom Keyboard Extension</h3>
<ul>
<li><a href="https://twitter.com/k_katsumi">@k_katsumi</a>さん</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8から開発できるようになったCustom Keyboardを作ろうというセッション</li>
<li>Custom Keyboardの作り方
<ul>
<li>documentProxy・UIKeyInput</li>
<li>hasText, insertText, deleteBackward</li>
</ul>
</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%AB%A4%CA%B4%C1%BB%FA%CA%D1%B4%B9">かな漢字変換</a>の実装が大変
<ul>
<li><a href="http://www.google.co.jp/ime/cgiapi.html">Google 日本語入力API</a>などを使ってカバーできる</li>
</ul>
</li>
<li>説明のあった k_katsumi さんが作られたキーボードはこちら
<ul>
<li><a href="http://d.hatena.ne.jp/KishikawaKatsumi/20140924/1411524632">親指シフトで日本語入力ができるカスタムキーボード「N+Keyboard」をリリースしました - 24/7 twenty-four seven</a></li>
</ul>
</li>
</ul>
<h1>まとめ</h1>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>のtipsをピックアップしてまとめましたが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>の発表も、ログの収集方法やtypefaceの管理、Bootstrapを使った研修など聞いて役に立つ面白いものが多かったです。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>は言語は違えど同じクライアントアプリということで、共通点は多そうですね。</p>
<p>potatotipsは毎回connpassページにて発表者を募集しています。
主催してくれる会社さんも募集されているようですので、興味のある方はぜひチェックしてみてください!</p>
<p>発表者のみなさん、Fablicのみなさん、本日はありがとうございました!</p>
<h1>関連記事</h1>
<ul>
<li>過去に開催されたポテチのまとめ記事はこちらです
<ul>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips1">クックパッドのLT会に参加してきたのでiOSのtipsをまとめる</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips2">第2回 #potatotips に参加してきたのでiOSのtipsをまとめる</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips3">第3回はヤフー開催! #potatotips で発表されたiOSのtipsまとめ</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips4">第4回 #potatotips で発表されたiOSに関する9つのtips</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips5">第5回 #potatotips で発表された12個のiOSのtipsをまとめる</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips6">第6回はUIEvolution開催! #potatotips で発表されたiOSのtipsまとめ</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips7">第7回はDeNA開催! #potatotips で発表されたiOSのtipsまとめ</a></li>
</ul>
</li>
</ul>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20131113/20131113234202.jpg" alt="f:id:himaratsu:20131113234202j:plain" title="f:id:himaratsu:20131113234202j:plain" class="hatena-fotolife" itemprop="image"></span></p>
himaratsu
世界最速のiOS 8のLT会に参加してきたので内容をまとめる #cmdevio
hatenablog://entry/12921228815733174224
2014-09-19T02:08:34+09:00
2022-02-24T19:50:50+09:00 ブログでおなじみのクラスメソッドさんの勉強会に参加させて頂きました。 iOS 8とかけて8本のLTで構成された勉強会で、iOS 8で追加された新機能やニッチな技術の紹介がありました。とても勉強になったので、メモと併せてまとめてみます。
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140919/20140919014523.jpg" alt="f:id:himaratsu:20140919014523j:plain" title="f:id:himaratsu:20140919014523j:plain" class="hatena-fotolife" itemprop="image" width="500" style="border: 1px solid #ccc"></span></p>
<p>ブログでおなじみのクラスメソッドさんの勉強会に参加させて頂きました。<br />
<iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fdev.classmethod.jp%2Fnews%2Fevent-lightning-talks-developers-io%2F" title="世界最速LT大会!? 新iOS 8発表!で登場した新機能・ニッチな技術を大公開!!-Developers.IO- | DevelopersIO" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8とかけて<b>8本のLTで構成された勉強会</b>で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8で追加された新機能やニッチな技術の紹介がありました。とても勉強になったので、メモと併せてまとめてみます。</p>
<p>なお、本家のまとめはこちらになりますのであわせてご参考ください:</p>
<ul>
<li><a href="http://dev.classmethod.jp/references/ios8-event-lightning-talks/">[イベントレポート] 世界最速LT大会!?新iOS 8発表!で登場した新機能・ニッチな技術を大公開!! #cmdevio | DevelopersIO</a></li>
</ul>
<h1>LT内容のまとめ</h1>
<h3>1.ついに<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8リリース!今までの歴史を振り返ってみる</h3>
<ul>
<li>大橋さん</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/39227288" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe></li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>の初期〜<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8までの変化を追う
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>の機能や<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>でできることの変化について</li>
<li>コミュニケーションやメディア、コマースのあり方など、現実世界の変化について</li>
</ul>
</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8技術の解説記事を200本出す予定。いま100本出している
<ul>
<li><a href="http://dev.classmethod.jp/referencecat/ios8/">http://dev.classmethod.jp/referencecat/ios8/</a></li>
</ul>
</li>
</ul>
<h3>2.Swiftの概要をざっくりと</h3>
<ul>
<li>田中さん</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/39229484" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe></li>
<li>Swiftの仕様一つずつ丁寧に説明</li>
<li>Swiftの変更点や注意点
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B7%BF%BF%E4%CF%C0">型推論</a>, Array, Dictionary, タプル, Optional <a class="keyword" href="http://d.hatena.ne.jp/keyword/Value">Value</a> など</li>
</ul>
</li>
<li>Swiftをつかってみて感想
<ul>
<li>良) シンプルな<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%EE%BC%F7">喜寿</a>tう, headerが不要でスッキリ, タプルなど便利なものが追加</li>
<li>悪) import記述不要が気持ち悪い, String/Array/Dictionaryが機能不足, Optional <a class="keyword" href="http://d.hatena.ne.jp/keyword/Value">Value</a></li>
</ul>
</li>
<li>Swift の公式ドキュメントはこちら:
<ul>
<li><a href="https://itunes.apple.com/us/book/the-swift-programming-language/id881256329?mt=11">Swiftの文法や言語仕様</a></li>
<li><a href="https://itunes.apple.com/us/book/using-swift-cocoa-objective/id888894773?mt=11">CocoaやObjective-Cと連携してのSwift</a></li>
</ul>
</li>
</ul>
<h3>3.CloudKitで始めるMBaaS入門</h3>
<ul>
<li>諏訪さん</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/39227377" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe></li>
<li>CloudKitとは
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a>が提供するBaaS</li>
<li>無料で10TBのDB, 1PBのアセットストレージが使える(1アプリあたり)</li>
</ul>
</li>
<li>CloudKitの使い方
<ul>
<li>Capabilityでチェック入れるだけで簡単スタート</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>の使い方の説明
<ul>
<li>短いコードでサーバーサイドの実装が書ける</li>
</ul>
</li>
<li>Subscription: ある条件を満たしたらpush通知、を実現できる</li>
</ul>
</li>
</ul>
<h3>4.新たな<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%FE%B7%C1%C2%E5%BF%F4">線形代数</a>ライブラリ Linear Algebra</h3>
<ul>
<li>安達さん</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/39230795" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe></li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%FE%B7%C1%C2%E5%BF%F4">線形代数</a>について
<ul>
<li>SwiftでLinear Algebraを使い、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CF%A2%CE%A9%CA%FD%C4%F8%BC%B0">連立方程式</a>を解く</li>
</ul>
</li>
<li>la_object_t と 遅延評価</li>
<li>活用ポイント
<ul>
<li>現在はUIViewのアフィン変換や、画像処理などで用いられている</li>
<li>将来的にはクライアントサイドでのデータ前処理などに有用ではないか</li>
</ul>
</li>
</ul>
<h3>5.PhotoKit入門</h3>
<ul>
<li>平屋さん</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/39234429" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe></li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8から登場したPhotoKitについて
<ul>
<li>AssetsFrameworkにとってかわるもの。写真の削除などが可能に</li>
</ul>
</li>
<li>Photos.framework について
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>標準の「写真」アプリと連動したモデルクラス
<ul>
<li>写真やビデオの自動整理
<ul>
<li>アセット(単体) PHAsset</li>
<li>モーメント(場所などでまとめたもの) PHAssetCollection</li>
<li>コレクション(モーメントより広いくくり) PHCollectionList</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>PhotosUI.framework について
<ul>
<li>PhotoEditing Extension 作成時に使用</li>
<li>「写真」アプリと連携するExtension</li>
</ul>
</li>
</ul>
<h3>6.測れる!パフォーマンス</h3>
<ul>
<li>深澤さん</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/39229522" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe></li>
<li>重い処理を、自動テストして数値化して判定する仕組みのつくりかた</li>
<li><code>measureBlock(){}</code> で測定された時間をもって判定する</li>
<li>計測の種類と方法</li>
</ul>
<h3>7.HealthKitで変わるミライ</h3>
<ul>
<li>荒川さん</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/39230636" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe></li>
<li>HealthKitとは何か
<ul>
<li>健康に関するアプリを簡単に実装できる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a></li>
<li>Health(ヘルスケア)のアプリのデータを用いる</li>
</ul>
</li>
<li>HealthKit開発のポイント
<ul>
<li>アプリ間をまたいだ健康情報の取得が可能</li>
<li>65種類以上のモデルオブジェクト、保存データの統計用のクエリがあらかじめ用意されている</li>
<li>ユーザープライバシーへの考慮が必要(認証してもらってはじめて情報利用できる)</li>
</ul>
</li>
<li>HealthKitの今後
<ul>
<li>個人の<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>にユーザーの情報を貯める
<ul>
<li>漏洩リスクもなく安心</li>
<li>必要に応じて必要な分だけユーザーはHealth情報を外部サービスに渡せる</li>
</ul>
</li>
<li>運用者ではなくユーザーに利益をもたらす</li>
</ul>
</li>
</ul>
<h3>8.新しいTest Flightの使い方</h3>
<ul>
<li>山本さん</li>
<li><iframe src="//www.slideshare.net/slideshow/embed_code/39234409" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe></li>
<li>TestFlightとは</li>
<li>内部テスターと外部テスター
<ul>
<li>内部: 開発内部向け
<ul>
<li>25ユーザー x 1ユーザーあたり10デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a></li>
<li>iTCの管理者・開発者以上の権限のメンバーに</li>
</ul>
</li>
<li>外部: 一般向け(現時点でまだ提供されていない)
<ul>
<li>1アプリ1000ユーザー x 1アカウントあたり10アプリが同時配信可</li>
<li>AppStoreレビュー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AC%A5%A4%A5%C9%A5%E9%A5%A4%A5%F3">ガイドライン</a>準拠</li>
</ul>
</li>
</ul>
</li>
<li>内部テスターで利用する際の手順とポイントの説明
<ul>
<li>UDIDは登録不要</li>
<li>Test Flightアプリで入れる
<ul>
<li>Test Flightアプリが<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8以上対応のため内部テスターは<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8以上が対象となる</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>まとめ</h3>
<p>当日の雰囲気や参加者のコメントを知りたい方はこちらからどうぞ:</p>
<ul>
<li><a href="http://togetter.com/li/720939">当日のTwitterまとめ - Togetter</a></li>
</ul>
<h1>まとめ</h1>
<p>90分ほどで<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 8の内容を広く知ることができ、とても勉強になりました。個人的にはTest Flightの実際の使い方、HealthKitが実現する未来などが面白かったです。<br />
また、本編とは関係ないのですが、発表者のみなさんのサンプルコードがすべてSwiftで書かれていてすごいなぁと感動しました。Swiftちょっとずつでも書いていかねば・・!</p>
<p>発表されたクラスメソッドのみなさん、参加者のみなさん、おつかれさまでした!</p>
<h1>おすすめ書籍</h1>
<p><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B00NBK9KC0/samura1-22/">[asin:B00NBK9KC0:detail]</a></p>
<p>まずは日本語でSwiftの概要を抑えたい方におすすめです。</p>
<h1>関連リンク</h1>
<ul>
<li><a href="http://himaratsu.hatenablog.com/entry/swift/tiqav">SwiftでTiqav APIを叩くビューワアプリを100行でつくったよ - Think Big Act Local</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips1">クックパッドのLT会に参加してきたのでiOSのtipsをまとめる - Think Big Act Local</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips7">第7回はDeNA開催! #potatotips で発表されたiOSのtipsまとめ - Think Big Act Local</a></li>
</ul>
himaratsu
Node.js でつくったサイトをスマホ対応させました
hatenablog://entry/12921228815732367977
2014-09-10T20:46:05+09:00
2022-02-24T19:51:02+09:00 先日、Node.js ではじめてWebサービスをつくりました。 とりあえず最低限のリリースを目指したのでPCのみ対応だったのですが、 今回スマホ画面にも対応したのでそのメモです。
<p>先日、Node.js ではじめて<a class="keyword" href="http://d.hatena.ne.jp/keyword/Web%A5%B5%A1%BC%A5%D3%A5%B9">Webサービス</a>をつくりました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fnode%2F3days" title="初めてのWebサービスを3日でつくってみた(Node.jsで) - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><br />
とりあえず最低限のリリースを目指したのでPCのみ対応だったのですが、<br />
今回<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>画面にも対応したのでそのメモです。</p>
<h2>できたもの</h2>
<p><a href="http://wedding.mashroom.in/">結婚式の余興.jp | スマートフォンにも対応</a></p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140909/20140909125827.jpg" alt="f:id:himaratsu:20140909125827j:plain" title="f:id:himaratsu:20140909125827j:plain" class="hatena-fotolife" itemprop="image" style="border:1px solid #ccc" width="250"></span></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>で見れる・・・!見れるぞ・・・・!!</p>
<h2>まず対応方針を考える</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>対応にはいくつかパターンがあります。レスポンシブルデザインにしたり、PCと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>でURLを分けたりなど。</p>
<p>今回は<b>PCと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>でURLは同じで、User Agentをみてhtmlと<a class="keyword" href="http://d.hatena.ne.jp/keyword/css">css</a>を出し分ける方法</b>にしました。<br />
特に深い理由はないですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/SNS">SNS</a>バッジなどを考えてURLは共通がいいなと思っていたのと、PCと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>で別のことに特化する(PCは投稿で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>は閲覧みたいな)気がしたのであまり共<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%CC%B2%BD">通化</a>する意味はないかなーと思ったためです。</p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>対応の作業の流れ</h2>
<p>こんな感じで進めました。</p>
<ol>
<li>User AgentをみてPCか<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>か判断する</li>
<li>PCなら<code>index.ejs</code>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>なら<code>index_m.ejs</code>を表示する</li>
<li>index_m.ejs に適用する用の<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>ファイルを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AC%A5%EA">ガリ</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AC%A5%EA">ガリ</a>書く</li>
</ol>
<p>それぞれの作業のメモを以下に書いていきます。</p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>対応の手順</h2>
<h4>1. User AgentをみてPCか<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>か判断する</h4>
<p>PCのみ対応だった時は、テンプレートエンジンは使わずに単純に <code>public/index.html</code> を表示する仕様でした。<br />
今回はアクセス時に出し分けが必要なので、以下のように変更。</p>
<p><strong>app.js</strong> (app.js)</p>
<pre class="code lang-javascript" data-lang="javascript" data-unlink><span class="synComment">// テンプレートエンジンは ejs を用いる</span>
app.set(<span class="synConstant">'views'</span>, __dirname + <span class="synConstant">'/views'</span>);
app.set(<span class="synConstant">'view engine'</span>, <span class="synConstant">'ejs'</span>);
<span class="synComment">// ルート(wedding.mashroom.in/)にアクセスされた場合、index.jsをcallする</span>
<span class="synIdentifier">var</span> routes = <span class="synIdentifier">{</span>
index:require(<span class="synConstant">'./routes/index.js'</span>),
<span class="synIdentifier">}</span>;
app.get(<span class="synConstant">'/'</span>, routes.index.index);
</pre>
<p>次に、ルートアクセスされた場合に呼ばれるindex.jsの中身が以下です。</p>
<p><strong>index.js</strong> (routes/index.js)</p>
<pre class="code lang-javascript" data-lang="javascript" data-unlink>exports.index = <span class="synIdentifier">function</span>(req, res)<span class="synIdentifier">{</span>
<span class="synComment">//User Agentの取得</span>
<span class="synIdentifier">var</span> userAgent = req.headers<span class="synIdentifier">[</span><span class="synConstant">'user-agent'</span><span class="synIdentifier">]</span>.toLowerCase();
<span class="synComment">// 表示するページ出し分け</span>
<span class="synStatement">if</span>(ua.indexOf(<span class="synConstant">"android"</span>) != -1
|| userAgent.indexOf(<span class="synConstant">"iphone"</span>) != -1
|| userAgent.indexOf(<span class="synConstant">"ipod"</span>) != -1)<span class="synIdentifier">{</span>
res.render(<span class="synConstant">'index_m'</span>, <span class="synIdentifier">{</span>title: <span class="synConstant">'スマホ用ページ'</span><span class="synIdentifier">}</span>);
<span class="synIdentifier">}</span>
<span class="synStatement">else</span><span class="synIdentifier">{</span>
res.render(<span class="synConstant">'index'</span>, <span class="synIdentifier">{</span>title:<span class="synConstant">'PC用ページ'</span><span class="synIdentifier">}</span>);
<span class="synIdentifier">}</span>
<span class="synIdentifier">}</span>;
</pre>
<p>リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トのヘッダにある<code>user-agent</code>を見て、表示ページを出し分けしています。</p>
<h4>2. PCなら<code>index.ejs</code>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>なら<code>index_m.ejs</code>を表示する</h4>
<p>手順1で出し分けまでできたので、実際に表示されるファイルを準備します。</p>
<pre class="code" data-lang="" data-unlink>PC用: index.ejs (views/index.ejs)
スマホ用: index_m.ejs (views/index_m.ejs)</pre>
<p>拡張子はejsですが、今回テンプレートは使わないので中身は普通のhtmlを書いています。これを配置するだけ。</p>
<p>ここで手順1でapp.jsに書いた記述を振り返ってみます。</p>
<pre class="code lang-javascript" data-lang="javascript" data-unlink><span class="synComment">// テンプレートエンジンは ejs を用いる</span>
app.set(<span class="synConstant">'views'</span>, __dirname + <span class="synConstant">'/views'</span>);
app.set(<span class="synConstant">'view engine'</span>, <span class="synConstant">'ejs'</span>);
</pre>
<p>この設定は、<code>res.render('index')</code> とした場合に <code>(__dirname)/views/ + index + .ejs</code> が表示されることを意味しているようです。必要に応じて<code>views</code>や<code>view engine</code>を変更すれば良さそうですね。</p>
<p>ここまでで、出し分けは完了しました。</p>
<h4>3. index_m.ejs に適用する用の<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>ファイルを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AC%A5%EA">ガリ</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AC%A5%EA">ガリ</a>書く</h4>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>を書き始める前に、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>向けの記述を index_m.js に追記します。</p>
<pre class="code lang-html" data-lang="html" data-unlink><span class="synIdentifier"><</span><span class="synStatement">meta</span><span class="synIdentifier"> </span><span class="synType">name</span><span class="synIdentifier">=</span><span class="synConstant">"viewport"</span><span class="synIdentifier"> </span><span class="synType">content</span><span class="synIdentifier">=</span><span class="synConstant">"width=device-width,initial-scale=1.0,user-scalable=yes"</span><span class="synIdentifier">></span>
</pre>
<p>この記述により<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>でアクセスした場合にフィットして表示されるようになります。</p>
<p>あとは<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AC%A5%EA">ガリ</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AC%A5%EA">ガリ</a>書くだけです。<br />
PCと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>は画面サイズや比率が大きく異なるので、どのコンテンツを表示すべきか等に注意しながらページを作ります。<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>の記述は以下の本を参考にしました。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4774161934?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51snYZMDUEL._SL500_.jpg" class="hatena-asin-detail-image" alt="HTML5 テクニックバイブル" title="HTML5 テクニックバイブル"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4774161934?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">HTML5 テクニックバイブル</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/HTML5%A5%B5%A5%DD%A1%BC%A5%BF%A1%BC%A5%BA" class="keyword">HTML5サポーターズ</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%BB%BD%D1%C9%BE%CF%C0%BC%D2">技術評論社</a></li></ul><a href="https://www.amazon.co.jp/dp/4774161934?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>開発時にブラウザ上で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>での見た目を確認するには<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D9%A5%ED%A5%C3%A5%D1">デベロッパ</a>ーツールを使用。下記の記事が分かりやすいです。 <iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Fait%2Farticles%2F1403%2F20%2Fnews050.html" title="PC版Chromeブラウザでスマホサイトをチェックする" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p>あとはデプロイして完成です。</p>
<h2>感想</h2>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>向けの<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>は初めて書いたが、コンテンツ間の距離やスクロール量を考慮した配置が重要だなと感じた</li>
<li>User-Agentによる出し分けは将来新しい端末(iWatchとか)が出たら対応が大変そう</li>
<li>レスポンシブルデザインで組むには、最初のhtml / <a class="keyword" href="http://d.hatena.ne.jp/keyword/css">css</a>の設計が非常に重要そう</li>
</ul>
<p>以上、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>対応時にやったことのメモでした。<br />
レスポンシブルデザインもつくってみたいですね!</p>
<h2>関連リンク</h2>
<p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fliginc.co.jp%2Fdesigner%2Farchives%2F7734" title="必読!5分でわかるレスポンシブWebデザインまとめ 制作編 | 株式会社LIG" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><br />
<iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fnode%2F3days" title="初めてのWebサービスを3日でつくってみた(Node.jsで) - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe></p>
himaratsu
初めてのWebサービスを3日でつくってみた(Node.jsで)
hatenablog://entry/12921228815730821048
2014-08-23T08:42:48+09:00
2022-02-24T19:51:03+09:00 Node.jsを触って勉強してたらWebサイトができました。 結婚式の余興.jp - 結婚式の余興を考えるときに参考になる動画を集めました Youtubeから結婚式の余興の動画を集めてくるサイトです。Web開発は初めてだったので、つくった流れや勉強の方法などをまとめてみます。 9/14追記)スマホ対応をやりました!
<p>Node.jsを触って勉強してたらWebサイトができました。</p>
<ul>
<li><a href="http://wedding.mashroom.in">結婚式の余興.jp - 結婚式の余興を考えるときに参考になる動画を集めました</a></li>
</ul>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Youtube">Youtube</a>から結婚式の余興の動画を集めてくるサイトです。Web開発は初めてだったので、つくった流れや勉強の方法などをまとめてみます。</p>
<p><strong>9/14追記)<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>対応をやりました!</strong>
<iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fnode%2Fsmartphone" title="Node.js でつくったサイトをスマホ対応させました - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<h2>普段は<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>アプリを書いています</h2>
<p>普段は<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>者をやっていて、仕事と趣味で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Objective-C">Objective-C</a>を書いてます。とても楽しくて2年くらい続けてるのですが、サーバーサイド書けたら幅が広がっていいな、とずっと思ってました。</p>
<p>普段の週末は<a href="http://himaratsu.hatenablog.com/entry/gomemo/release">個人アプリを作ったり</a>してるのですが、夏休みだし新しいことやろうと思ってNode.jsを触ってみました。</p>
<h1>つくったもの</h1>
<p><a href="http://wedding.mashroom.in/" target="_blank"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140820/20140820235840.png" alt="f:id:himaratsu:20140820235840p:plain" title="f:id:himaratsu:20140820235840p:plain" class="hatena-fotolife" itemprop="image" width="500" style="border:1px solid #ccc"></span></a></p>
<p><a href="http://wedding.mashroom.in">結婚式の余興.jp - 結婚式の余興を考えるときに参考になる動画を集めました</a></p>
<p>結婚式の余興動画がまとまっていて、だら見できるサイトです。最近友人の結婚式が多くて、余興の動画をウォッチすることが多かったのでまとまってて欲しいと思ってつくりました。</p>
<p>機能的には<a class="keyword" href="http://d.hatena.ne.jp/keyword/Youtube">Youtube</a>にあがっている余興動画を自動でとってきて登録してくれます。使った技術は以下のような感じ。</p>
<ul>
<li>Node.js</li>
<li>MongoDB</li>
<li>heroku</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Youtube">Youtube</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a></li>
</ul>
<h1>開発3日間を振り返る</h1>
<h3>始める前のスペック</h3>
<ul>
<li>Node.jsは使ったことない</li>
<li>RESTfulとかは何となく分かってる</li>
<li>言語はほぼ<a class="keyword" href="http://d.hatena.ne.jp/keyword/Objective-C">Objective-C</a>しか書いたことないレベル</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Rails">Rails</a>で何かつくろうとして2回くらい挫折</li>
</ul>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby%20on%20Rails">Ruby on Rails</a> か Node.js のどっちかで作ろうと思って、周りに詳しい人の多い(詰まったら聞きやすい) Node.js を選びました。</p>
<h3><1日目></h3>
<h4>やったこと</h4>
<ul>
<li>本を1冊やった(関係ありそうな部分だけ)</li>
<li>環境設定から簡単なリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トくらいまで同僚と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>でつくる</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>をいじってレイアウトを調整する</li>
</ul>
<p>まずはnode.jsの全体像を把握すべく、緑の本を読みました。これを読むとnodeの実行方法やよく使うモジュール、expressとかmongoがなんとなく分かりました。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4797370904?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/510pDzY1u9L._SL500_.jpg" class="hatena-asin-detail-image" alt="はじめてのNode.js -サーバーサイドJavaScriptでWebアプリを開発する-" title="はじめてのNode.js -サーバーサイドJavaScriptでWebアプリを開発する-"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4797370904?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">はじめてのNode.js -サーバーサイドJavaScriptでWebアプリを開発する-</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%BE%BE%C5%E7%20%B9%C0%C6%BB" class="keyword">松島 浩道</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/SB%A5%AF%A5%EA%A5%A8%A5%A4%A5%C6%A5%A3%A5%D6">SBクリエイティブ</a></li></ul><a href="https://www.amazon.co.jp/dp/4797370904?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>での入門は最高</h5>
<p>なんとなく分かったとこで、node.jsに詳しい友人と夜ご飯食べながら<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>。環境設定とか<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の設計とか、最近のトレンドをあわせて教えてくれてめちゃめちゃ助かりました。GETでmongoに入ってるデータを一覧取得して、POSTで新規登録する、みたいな部分の実装まで付き合ってもらいました。</p>
<h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>が楽しい</h5>
<p>家帰ってから興奮の赴くままに<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>を書いて、見た目を良い感じに整えました。<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>久しぶりに書いたけどめちゃめちゃ楽しかったです。アプリはアイコンの重要度が高いけど、Webはレイアウトの比重が大きいのでレイアウト好きな自分には嬉しい。</p>
<p>途中<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>が迷ったときはこの本で復習しました。ポイントが押さえられていてこれ一冊でサイトが1つ作れる便利ブックです。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4774161934?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51snYZMDUEL._SL500_.jpg" class="hatena-asin-detail-image" alt="HTML5 テクニックバイブル" title="HTML5 テクニックバイブル"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4774161934?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">HTML5 テクニックバイブル</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/HTML5%A5%B5%A5%DD%A1%BC%A5%BF%A1%BC%A5%BA" class="keyword">HTML5サポーターズ</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%BB%BD%D1%C9%BE%CF%C0%BC%D2">技術評論社</a></li></ul><a href="https://www.amazon.co.jp/dp/4774161934?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>ここで1日目は終了。朝4時くらいに寝ました。</p>
<h3><2日目></h3>
<h4>やったこと</h4>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A6%A5%A3%A5%B8%A5%A7%A5%C3%A5%C8">ウィジェット</a>の配置</li>
<li>ページング処理の実装</li>
<li>カスタムフォントの適用</li>
<li>Herokuへのデプロイ</li>
</ul>
<h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A6%A5%A3%A5%B8%A5%A7%A5%C3%A5%C8">ウィジェット</a></h5>
<p>動画だけで寂しかったので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A6%A5%A3%A5%B8%A5%A7%A5%C3%A5%C8">ウィジェット</a>を配置しました。初めてだったのですが<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>のサイトがよく出来ていて迷わず置けました。<br />
「結婚式の余興」で検索した結果のタイムラインがサイトの右側に並んでいます。</p>
<ul>
<li><a href="https://dev.twitter.com/ja/docs/embedded-timelines">https://dev.twitter.com/ja/docs/embedded-timelines</a></li>
</ul>
<h5>ページング処理の実装</h5>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140821/20140821002145.png" alt="f:id:himaratsu:20140821002145p:plain" title="f:id:himaratsu:20140821002145p:plain" class="hatena-fotolife" itemprop="image" width="350" style="border:1px solid #ccc"></span></p>
<p>また、ページングの処理や動画の追加フォームなど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/javascript">javascript</a>をいじって細かい部分を作りました。<a class="keyword" href="http://d.hatena.ne.jp/keyword/javascript">javascript</a>もほとんど書いたことはなかったのですが、詰まったら本を読み返すスタイルで前進しました。使った本はこれです。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/477414813X?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51yrjFsf-2L._SL500_.jpg" class="hatena-asin-detail-image" alt="パーフェクトJavaScript (PERFECT SERIES 4)" title="パーフェクトJavaScript (PERFECT SERIES 4)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/477414813X?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">パーフェクトJavaScript (PERFECT SERIES 4)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%B0%E6%BE%E5%20%C0%BF%B0%EC%CF%BA" class="keyword">井上 誠一郎</a>,<a href="http://d.hatena.ne.jp/keyword/%C5%DA%B9%BE%20%C2%F3%CF%BA" class="keyword">土江 拓郎</a>,<a href="http://d.hatena.ne.jp/keyword/%C9%CD%CA%D5%20%BE%AD%C2%C0" class="keyword">浜辺 将太</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%BB%BD%D1%C9%BE%CF%C0%BC%D2">技術評論社</a></li></ul><a href="https://www.amazon.co.jp/dp/477414813X?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>サイ本ほど重くなく、かつ一通り網羅していて助かる感じの本です。</p>
<h5>カスタムフォントの適用</h5>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140821/20140821001541.png" alt="f:id:himaratsu:20140821001541p:plain" title="f:id:himaratsu:20140821001541p:plain" class="hatena-fotolife" itemprop="image" width="400" style="border:1px solid #ccc"></span></p>
<p>フォントくらいは凝ろうと思って、カスタムフォントを使いました。手描き風の可愛いフォントを探して<strong>kiloji</strong>にしました。</p>
<ul>
<li><a href="http://www.ez0.net/distribution/font/kiloji/">externalStyle.html</a></li>
</ul>
<h5>Herokuにデプロイして公開</h5>
<p>最後にHerokuにデプロイします。Node.jsをHerokuにデプロイするのは以下のページの手順を参考に進め、最後にHerokuにMongoHQを追加して完了。</p>
<ul>
<li><a href="https://devcenter.heroku.com/articles/getting-started-with-nodejs">Getting Started on Heroku with Node.js | Heroku Dev Center</a></li>
</ul>
<p>「結婚式の余興.jp」がインターネット上に公開されたここまでで2日。</p>
<h3><3日目></h3>
<h4>やったこと</h4>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Youtube">Youtube</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>をたたいて動画を自動追加する<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を作成</li>
<li>Heroku Schedulerを使って定期的に実行</li>
<li>カスタム<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>を適用</li>
</ul>
<p>手動運用はいけてないので、動画を集めてくる部分を自動化しました。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Youtube">Youtube</a>から取得→結婚式の余興.jpに追加 が走る<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を作り、それを定期的にたたくバッヂを書きました。</p>
<p>定期的な実行は Heroku Scheduler で行い、<code>bin</code> 以下のパスを指定するだけでスンナリ動きました。参考ページは以下。</p>
<ul>
<li><a href="http://www.spacjer.com/blog/2014/02/10/defining-node-dot-js-task-for-heroku-scheduler/">Defining Node.js task for Heroku Scheduler – Rafal Spacjer blog</a></li>
</ul>
<p>最後に、公開<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>である<code>wedding.mashroom.in</code>をあてて完成です。</p>
<h1>感想</h1>
<ul>
<li>アプリみたいにビルドで時間がかからなくて良い</li>
<li>書いたコードがなくサクサク反映されるので楽しい</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>はアイコン作ったりのスキルがなくても通用するので楽しい</li>
<li>勉強してから作るより、作りたいものドリブンで勉強するのが性に合ってると思った</li>
</ul>
<p>環境設定とか最初のところでつまずくことが多いので、そこをサポートしてもらえて最高に入門しやすかったです。改めて友人くんありがとう!</p>
<h1>小話:カスタム<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>の設定</h1>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C6%C8%BC%AB%A5%C9%A5%E1%A5%A4%A5%F3">独自ドメイン</a>、お名前.comで設定したら反映されなくて3日くらいロスしました。<a href="http://qiita.com/numa08/items/d4ad9454f0baefc8c784">ここのサイトを参考にして</a> Dozens.jp を使うようにしたら2時間くらいで反映されたけど何が原因だったんだろう…。</p>
<ul>
<li><a href="https://dozens.jp/">https://dozens.jp/</a></li>
</ul>
<h1>次やること</h1>
<p>次はサーバーサイド+<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>アプリを作ってみたいと思い、探してみたら良い感じの本を発見しました。読んで試してみようと思います。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4844334476?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51omKgN0AsL._SL500_.jpg" class="hatena-asin-detail-image" alt="RailsとiPhoneではじめるアプリケーション開発" title="RailsとiPhoneではじめるアプリケーション開発"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4844334476?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">RailsとiPhoneではじめるアプリケーション開発</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%B7%AA%C5%C4%20%CD%B3%BA%DA" class="keyword">栗田 由菜</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%D7%A5%EC%A5%B9">インプレス</a></li></ul><a href="https://www.amazon.co.jp/dp/4844334476?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p><strong>9/14追記)<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>対応をやりました!</strong>
<iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhimaratsu.hatenablog.com%2Fentry%2Fnode%2Fsmartphone" title="Node.js でつくったサイトをスマホ対応させました - Think Big Act Local" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe></p>
himaratsu
KeynoteでAppStoreのスクリーンショットをつくる
hatenablog://entry/12921228815730331440
2014-08-16T14:01:42+09:00
2022-02-24T19:50:49+09:00 最近 Go Memo という個人開発のアプリ をリリースしたのですが、AppStoreに載せるスクリーンショットをKeynoteで作ってみました。手軽にできて便利だったのでやり方を紹介してみます。
<p>最近 <a href="http://himaratsu.hatenablog.com/entry/gomemo/release">Go Memo という個人開発のアプリ</a> をリリースしたのですが、AppStoreに載せる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A1%BC%A5%F3%A5%B7%A5%E7%A5%C3%A5%C8">スクリーンショット</a>を<a class="keyword" href="http://d.hatena.ne.jp/keyword/Keynote">Keynote</a>で作ってみました。手軽にできて便利だったのでやり方を紹介してみます。</p>
<p>最終的にはこんな感じのが出来上がりました:</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140816/20140816001415.jpg" alt="f:id:himaratsu:20140816001415j:plain" title="f:id:himaratsu:20140816001415j:plain" class="hatena-fotolife" itemprop="image" width="250" style="border:1px solid #ccc"></span>
<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140816/20140816140112.jpg" alt="f:id:himaratsu:20140816140112j:plain" title="f:id:himaratsu:20140816140112j:plain" class="hatena-fotolife" itemprop="image" width="250" style="border:1px solid #ccc"></span></p>
<p><a href="https://itunes.apple.com/app/id903841654?l=ja&ls=1&mt=8">Go Memo を AppStore で見る</a></p>
<p>それっぽいのが出来てる気がします。</p>
<h2>前提</h2>
<p>AppStoreにアプリを申請する時、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A1%BC%A5%F3%A5%B7%A5%E7%A5%C3%A5%C8">スクリーンショット</a>が必要です。<br />
アプリ名のすぐ下に表示されるので、どんなアプリか?を知ってもらうためにスクショは非常に重要です。初期の頃は単純にアプリの各画面のキャプチャが貼られていました。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140816/20140816033056.jpg" alt="f:id:himaratsu:20140816033056j:plain" title="f:id:himaratsu:20140816033056j:plain" class="hatena-fotolife" itemprop="image" width="250" style="border:1px solid #ccc"></span></p>
<p>しかし、この部分には、</p>
<ul>
<li>640x1136(4inchの画面サイズ)</li>
<li>640x960(3.5inchの画面サイズ)</li>
</ul>
<p>であればどんな画像でも入れられます。サービスの魅力がより伝わるように、現在では以下のように様々な彩りが施されたスクショはが載せられることが多くなってきました。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140816/20140816002433.jpg" alt="f:id:himaratsu:20140816002433j:plain" title="f:id:himaratsu:20140816002433j:plain" class="hatena-fotolife" itemprop="image" width="250" style="border:1px solid #ccc"></span>
<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140816/20140816002418.jpg" alt="f:id:himaratsu:20140816002418j:plain" title="f:id:himaratsu:20140816002418j:plain" class="hatena-fotolife" itemprop="image" width="250" style="border:1px solid #ccc"></span></p>
<p>こういった画像は <a class="keyword" href="http://d.hatena.ne.jp/keyword/Photoshop">Photoshop</a> などがあれば簡単に作れるのかもしれませんが、自分はソフトを持っていません。新しいツールを使うのも、学習するのが大変です。</p>
<p>そこで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Keynote">Keynote</a>を使って<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A1%BC%A5%F3%A5%B7%A5%E7%A5%C3%A5%C8">スクリーンショット</a>を作ってみました。</p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Keynote">Keynote</a>を使って<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A1%BC%A5%F3%A5%B7%A5%E7%A5%C3%A5%C8">スクリーンショット</a>を作る</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Keynote">Keynote</a>を起動し、スライドのサイズを 640x1136 に変更します。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140816/20140816002723.png" alt="f:id:himaratsu:20140816002723p:plain" title="f:id:himaratsu:20140816002723p:plain" class="hatena-fotolife" itemprop="image" style="border:1px solid #ccc"></span></p>
<p>オブジェクトや<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>のフレーム素材画像を配置して、レイアウトします。
マスクやインスタントアルファを使えば簡単に作ることができます。</p>
<p>マスク・インスタントアルファの使い方はこちらのスライドが分かりやすいです。</p>
<ul>
<li><a href="http://www.slideshare.net/techblogyahoo/yxdena">プロトタイピングと定性調査のすすめ | SlideShare</a></li>
</ul>
<p>最終的には以下のように出来上がります。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140816/20140816003105.png" alt="f:id:himaratsu:20140816003105p:plain" title="f:id:himaratsu:20140816003105p:plain" class="hatena-fotolife" itemprop="image" style="border:1px solid #ccc"></span></p>
<p>これを <b>ファイル > 書き出す > イメージ</b> から<a class="keyword" href="http://d.hatena.ne.jp/keyword/png">png</a>形式で書き出せば完成です。</p>
<h3>3.5inchサイズの準備も簡単</h3>
<p>640x960 サイズの用意も簡単です。<br />
3.5インチの端末で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A1%BC%A5%F3%A5%B7%A5%E7%A5%C3%A5%C8">スクリーンショット</a>をわざわざ撮る必要はなく、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Keynote">Keynote</a>でスライドのサイズにあわせて文字サイズや画像の配置を調整するだけ。申請作業の途中に「あ、3.5インチのスクショ撮らなきゃ…」とならなくて楽ですね。</p>
<h1>まとめ</h1>
<p>デザイナーさんに作ってもらったり、自分で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Photoshop">Photoshop</a>を使える場合は必要ないと思いますが、自分は一人で作ってサッと出したい場合があるので良いなと思いました。
使い慣れたツールである<a class="keyword" href="http://d.hatena.ne.jp/keyword/Keynote">Keynote</a>で作れるというのも良いですね。</p>
<p><a href="http://c-note.chatwork.com/post/93858598435/keynote">最近はKeynoteでプロトタイピングを作る</a> みたいな話も出てきてますし、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Keynote">Keynote</a>好きの自分はちょっと嬉しいです。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Keynote">Keynote</a>でスクショ作り、良ければ試してみてください◎</p>
<h5><宣伝></h5>
<p>今回の題材となった Go Memo のダウンロードはこちらから:</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/https">https</a>://<a class="keyword" href="http://d.hatena.ne.jp/keyword/itunes">itunes</a>.<a class="keyword" href="http://d.hatena.ne.jp/keyword/apple">apple</a>.com/jp/app/id903841654?mt=8&at=10l8JW&ct=hatenablog</p>
<h1>Special Thanks</h1>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Keynote">Keynote</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A1%BC%A5%F3%A5%B7%A5%E7%A5%C3%A5%C8">スクリーンショット</a>を作る発想と方法は <a href="http://blog.hatena.ne.jp/shoma2da/">id:shoma2da</a> くんに教えてもらいました。ありがとうございます!</p>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/Keynote">Keynote</a>の購入はこちらから</h3>
<ul>
<li><a href="https://itunes.apple.com/jp/app/keynote/id409183694?mt=12">‎「Keynote」をApp Storeで</a></li>
</ul>
<h1>関連書籍</h1>
<p><a href="https://www.amazon.co.jp/exec/obidos/ASIN/4274065669/samura1-22/">[asin:4274065669:detail]</a></p>
himaratsu
個人アプリの爆速開発を支えてくれたiOSの便利ライブラリを紹介する
hatenablog://entry/12921228815730194524
2014-08-15T09:26:23+09:00
2022-02-24T19:50:51+09:00 先日 Go MemoというiOSアプリをリリースしました。 「あとで行く」ためのアプリ、Go Memoをリリースしました Go Memoは週末4日間くらいで作ってリリースしたアプリなのですが、こうしてスピードを出せたのは便利なライブラリのおかげです。 この記事ではGo Memoで使ったライブラリを紹介しようと思います。
<p>先日 Go Memoという<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>アプリをリリースしました。</p>
<ul>
<li><a href="http://himaratsu.hatenablog.com/entry/gomemo/release">「あとで行く」ためのアプリ、Go Memoをリリースしました</a></li>
</ul>
<p>Go Memoは週末4日間くらいで作ってリリースしたアプリなのですが、こうしてスピードを出せたのは便利なライブラリのおかげです。</p>
<p>この記事ではGo Memoで使ったライブラリを紹介しようと思います。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140815/20140815001206.jpg" alt="f:id:himaratsu:20140815001206j:plain" title="f:id:himaratsu:20140815001206j:plain" class="hatena-fotolife" itemprop="image" width="250" style="border:1px solid #ccc"></span></p>
<h1>便利な<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>ライブラリ</h1>
<h2><a href="https://github.com/AFNetworking/AFNetworking">AFNetworking</a></h2>
<p>言わずとしれた定番ライブラリ。作者の mattt さんも非常に有名です。サーバーとのHTTP通信はほとんどこれに頼っていて、NSURLSession とか自分で書いてないです。</p>
<p>Go Memoでは <a class="keyword" href="http://d.hatena.ne.jp/keyword/foursquare">foursquare</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> をたたく所で利用しています。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink><span class="synType">NSDictionary</span> *params = ...;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:<span class="synConstant">@"https://api.foursquare.com/v2/venues/search"</span>
parameters:params
success:^(AFHTTPRequestOperation *operation, <span class="synType">id</span> responseObject) {
<span class="synComment">// ... ここでレスポンスを処理 ...</span>
} failure:^(AFHTTPRequestOperation *operation, <span class="synType">NSError</span> *error) {
<span class="synComment">// ... ここにエラー処理 ...</span>
}];
</pre>
<h2><a href="https://github.com/magicalpanda/MagicalRecord">MagicalRecord</a></h2>
<p>CoreDataを簡易に扱うためのライブラリ。データの永続化によく使われるCoreDataはとても便利なのですが、巨大すぎて使いこなすまでには時間がかかります(色々とクセがある)。<br />
MagicalRecordはそんなCoreDataへのアクセスを簡易にしてくれるライブラリです。</p>
<p>Go Memo では登録した場所の情報をCoreDataに保存しており、MagicalRecordで扱っています。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink><span class="synComment">// 登録したメモ(場所の情報)を全件取得</span>
<span class="synIdentifier">- </span>(<span class="synType">NSArray</span> *)getAllMemos {
[MagicalRecord setupCoreDataStack];
_magicalContext = [NSManagedObjectContext MR_contextForCurrentThread];
<span class="synStatement">return</span> [PlaceMemo MR_findAllSortedBy:<span class="synConstant">@"postdate"</span> ascending:<span class="synConstant">NO</span>]
}
</pre>
<p>MagicalRecordの概要を知るには以下の記事が良いと思います。</p>
<ul>
<li><a href="http://www.atmarkit.co.jp/ait/articles/1307/10/news017.html">iOSアプリのデータ操作はMagical Recordでマジ簡単! - @IT</a></li>
</ul>
<p>MagicalRecordは便利ですが、CoreDataの仕組みをちゃんと理解した上で使いたいと思う方もいると思います。そんな方にはこの書籍がおすすめです。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4798039799?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/41l4NOjbb8L._SL500_.jpg" class="hatena-asin-detail-image" alt="iOS Core Data徹底入門" title="iOS Core Data徹底入門"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4798039799?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">iOS Core Data徹底入門</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%D4%A2%B5%EF%20%B5%AE%B9%C0" class="keyword">國居 貴浩</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%A8%CF%C2%A5%B7%A5%B9%A5%C6%A5%E0">秀和システム</a></li></ul><a href="https://www.amazon.co.jp/dp/4798039799?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>そもそもデータの永続化とは?の部分から丁寧に説明されています。</p>
<h2><a href="https://github.com/TransitApp/SVProgressHUD">SVProgressHUD</a></h2>
<p>ローディング中にインジケータを表示するライブラリ。通常のインジケータの他、ラベルつきのインジケータ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%EC">プログレ</a>スインジケータなどを簡単な記述で表示できるのが魅力です。</p>
<p><img src="https://camo.githubusercontent.com/6ed028acbf67707d622344e0ef1bc3b098425b50/687474703a2f2f662e636c2e6c792f6974656d732f32473146315a304d306b306832553356317033392f535650726f67726573734855442e676966" alt="" /></p>
<pre class="code lang-objc" data-lang="objc" data-unlink>[SVProgressHUD show]; <span class="synComment">// 表示する</span>
[SVProgressHUD dismiss]; <span class="synComment">// 隠す</span>
</pre>
<p>なお、似たライブラリとして <a href="https://github.com/jdg/MBProgressHUD">MBProgressHUD
</a> があります。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>のstar数はこちらの方が多いようですが、僕は慣れで SVProgressHUD を使っています。</p>
<p>ユーザーの待ち時間の体験を少しでも良くするのに便利ですね。</p>
<h2><a href="https://github.com/ryanmaxwell/UIAlertView-Blocks">UIAlertView+Blocks</a></h2>
<p>UIAlertView で Blocks の記述を可能にするライブラリです。<br />
通常の UIAlertView でユーザーに選択肢を提示させる場合 <a class="keyword" href="http://d.hatena.ne.jp/keyword/delegate">delegate</a> を使うことになると思いますが、複数のアラートを扱う場合など tag で判定する必要がありコードが煩雑になってしまいます。</p>
<p>UIAlertView+Blocks を使えば処理を簡潔に書くことができます。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink>[UIAlertView showWithTitle:<span class="synConstant">@""</span>確認
message:<span class="synConstant">@"本当に削除しますか?"</span>
cancelButtonTitle:<span class="synConstant">@"キャンセル"</span>
otherButtonTitles:<span class="synStatement">@</span>[<span class="synConstant">@"削除する"</span>]
tapBlock:^(UIAlertView *alertView, <span class="synType">NSInteger</span> buttonIndex) {
<span class="synStatement">if</span> (alertView.cancelButtonIndex != buttonIndex) {
<span class="synComment">// 削除する</span>
[<span class="synStatement">self</span> deleteMemo];
}
}];
</pre>
<p>UIKit の Blocks 拡張としては <a href="https://github.com/zwaldowski/BlocksKit">BlocksKit</a> が有名ですが、BlocksKit は巨大すぎて別ライブラリと衝突することがあるため、最近は最低限のBlocks拡張を入れるだけにしています。</p>
<h2><a href="https://github.com/ryanmaxwell/UIActionSheet-Blocks">UIActionSheet+Blocks</a></h2>
<p>UIAlertView+Blocks と同じ作者である ryanmaxwell さんのライブラリ。こちらは UIActionSheet を blocks で書けるようになります。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink>[UIActionSheet showInView:<span class="synStatement">self</span>.view
withTitle:<span class="synConstant">@"経路を別アプリで開く"</span>
cancelButtonTitle:<span class="synConstant">@"キャンセル"</span>
destructiveButtonTitle:<span class="synConstant">nil</span>
otherButtonTitles:<span class="synStatement">@</span>[<span class="synConstant">@"iOSの地図で開く"</span>,
<span class="synConstant">@"Google Mapで開く"</span>]
tapBlock:^(UIActionSheet *actionSheet, <span class="synType">NSInteger</span> buttonIndex) {
<span class="synStatement">if</span> (actionSheet.cancelButtonIndex != buttonIndex) {
<span class="synStatement">if</span> (buttonIndex == <span class="synConstant">0</span>) {
[<span class="synStatement">self</span> openNativeMap];
}
<span class="synStatement">else</span> <span class="synStatement">if</span> (buttonIndex == <span class="synConstant">1</span>) {
[<span class="synStatement">self</span> openGoogleMap];
}
}
}];
</pre>
<p>やはり処理がまとめられるので便利です。</p>
<h2><a href="https://github.com/rs/SDWebImage">SDWebImage</a></h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>における画像フェッチャーの決定版的なライブラリです。キャッシュ処理やWebからのロードの処理、読み込み失敗時の扱いなどを非常に良い感じに行ってくれます。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink><span class="synComment">// 画像をURLから読み込み</span>
<span class="synComment">// キャッシュにあればキャッシュから、なければURLから取得する</span>
[cell.photoImageView setImageWithURL:[NSURL fileURLWithPath:_memo.imageFilePath]];
</pre>
<p>SDWebImage については <a href="http://blog.hatena.ne.jp/ninjinkun/">id:ninjinkun</a> さんのスライドが大変参考になります。</p>
<ul>
<li><a href="https://speakerdeck.com/ninjinkun/sdwebimagewo1nian-ban-shi-tutemita">SDWebImageを1年半使ってみた</a></li>
</ul>
<h2><a href="https://github.com/mwaterfall/MWPhotoBrowser">MBPhotoBrowser</a></h2>
<p>写真をフルスクリーン表示したりするのに便利なライブラリです。ナビゲーションバーを隠したり、グリッド表示に切り替えたりなど、色々と細かな設定も可能です。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140815/20140815004451.jpg" alt="f:id:himaratsu:20140815004451j:plain" title="f:id:himaratsu:20140815004451j:plain" class="hatena-fotolife" itemprop="image" width="250"></span></p>
<h5>呼び出し箇所</h5>
<pre class="code lang-objc" data-lang="objc" data-unlink>MWPhotoBrowser *browser = [[MWPhotoBrowser alloc] initWithDelegate:<span class="synStatement">self</span>];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:browser];
[<span class="synStatement">self</span> presentViewController:nav animated:<span class="synConstant">YES</span> completion:<span class="synConstant">nil</span>];
</pre>
<h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/delegate">delegate</a>メソッド</h5>
<pre class="code lang-objc" data-lang="objc" data-unlink><span class="synPreProc">#pragma mark -</span>
<span class="synPreProc">#pragma mark MWPhotoBrowserDelegate</span>
<span class="synIdentifier">- </span>(<span class="synType">NSUInteger</span>)numberOfPhotosInPhotoBrowser:(MWPhotoBrowser *)photoBrowser {
<span class="synStatement">return</span> <span class="synStatement">self</span>.foursquarePhotos.count;
}
<span class="synIdentifier">- </span>(<span class="synType">id</span> <MWPhoto>)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(<span class="synType">NSUInteger</span>)index {
<span class="synStatement">if</span> (index < <span class="synStatement">self</span>.foursquarePhotos.count)
<span class="synStatement">return</span> [<span class="synStatement">self</span>.foursquarePhotos objectAtIndex:index];
<span class="synStatement">return</span> <span class="synConstant">nil</span>;
}
</pre>
<h3><a href="https://github.com/PrideChung/FontAwesomeKit">FontAwesomeKit</a></h3>
<p><a href="http://fortawesome.github.io/Font-Awesome/">FontAwesome</a> を<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>でも扱えるようにするライブラリです。Go memoではトップページ左上のギアアイコン(設定アイコン)に使っています。<br />
呼び出し方も簡単で、以下のようにコールするだけです。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink>FAKFontAwesome *icon = [FAKFontAwesome gearIconWithSize:<span class="synConstant">20</span>];
<span class="synStatement">self</span>.leftBarButtonItem.image = [icon imageWithSize:CGSizeMake(<span class="synConstant">20</span>, <span class="synConstant">20</span>)];
</pre>
<p>FontAwesome を扱うライブラリは他にも存在しますが、他のライブラリではアイコンをUILabel として扱うのに対して、UIImage のオブジェクトを生成できる点が嬉しくて今回はこれを選びました。</p>
<p>アイコンを自分で作るのは大変、という方は FontAwesome に頼りましょう。</p>
<h5>参考</h5>
<ul>
<li><a href="http://tnakamura.hatenablog.com/entry/2013/12/10/113954">FontAwesomeKit の使い勝手が良かったので移行した話 - present</a></li>
</ul>
<h1>まとめ</h1>
<p>以上、8つのライブラリを紹介しました。<br />
どれもドがつく定番ライブラリだけあって非常に便利で、開発効率を爆上げしてくれます。ライブラリに依存しすぎないよう気をつけつつ積極的に利用していきたいですね。</p>
<p>また、自分でも便利ライブラリを作って公開したい機運が高まってきたので頑張ります。</p>
<h5>宣伝</h5>
<p>今回の題材となった Go Memo のダウンロードはこちらから:</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/https">https</a>://<a class="keyword" href="http://d.hatena.ne.jp/keyword/itunes">itunes</a>.<a class="keyword" href="http://d.hatena.ne.jp/keyword/apple">apple</a>.com/jp/app/id903841654?mt=8&at=10l8JW&ct=hatenablog</p>
<h1>関連リンク</h1>
<ul>
<li><a href="https://codeiq.jp/magazine/2014/06/11630/">https://codeiq.jp/magazine/2014/06/11630/</a></li>
<li><a href="http://blog.mokosoft.com/entry/2013/12/17/180337">iOS開発で使って便利だったオープンソースライブラリ | Mokosoft開発者ブログ</a></li>
</ul>
<h1>これから<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>開発を勉強する方へ</h1>
<p>↓ステップごとの説明が丁寧で、大変分かりやすいオススメの記事です。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fxavier.hateblo.jp%2Fentry%2F2014%2F09%2F22%2F100201" title="Swiftで初めて動きのあるゲームを開発する人向けチュートリアル(なんとかストライクを例にStep by Step解説) - こんにゃくマガジン" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe></p>
<p><a href="http://xavier.hateblo.jp/entry/2014/09/22/100201">Swiftで初めて動きのあるゲームを開発する人向けチュートリアル(なんとかストライクを例にStep by Step解説) - こんにゃくマガジン</a></p>
<h1>関連書籍</h1>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4798036277?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/31W2OuJOFcL._SL500_.jpg" class="hatena-asin-detail-image" alt="iOSオープンソースライブラリ徹底活用" title="iOSオープンソースライブラリ徹底活用"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4798036277?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">iOSオープンソースライブラリ徹底活用</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%B5%C6%C5%C4%20%B9%E4" class="keyword">菊田 剛</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%A8%CF%C2%A5%B7%A5%B9%A5%C6%A5%E0">秀和システム</a></li></ul><a href="https://www.amazon.co.jp/dp/4798036277?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>有名な<a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a>の中身、使い方などが紹介されています。ボリューミー
!</p>
himaratsu
「あとで行く」ためのアプリ、Go Memoをリリースしました
hatenablog://entry/12921228815730087560
2014-08-12T22:14:03+09:00
2022-02-24T19:50:50+09:00 久しぶりに個人アプリをリリースしました。 「あとで読む」ならぬ、「あとで行く」がコンセプトのiPhoneアプリです。
<p>久しぶりに個人アプリをリリースしました。<br />
「あとで読む」ならぬ、<strong>「あとで行く」</strong>がコンセプトの<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone%A5%A2%A5%D7%A5%EA">iPhoneアプリ</a>です。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140812/20140812213906.png" alt="f:id:himaratsu:20140812213906p:plain" title="f:id:himaratsu:20140812213906p:plain" class="hatena-fotolife" itemprop="image" width="100"></span>
</p>
<p>「あとで行く」ためのアプリ Go Memo - AppStore
<a href="https://itunes.apple.com/jp/app/id903841654?mt=8">https://itunes.apple.com/jp/app/id903841654?mt=8</a></p>
<h2>つくったもの</h2>
<p>「あ、このお店良さそう。今度来よう!」と思った時に、記録しておいて後で見返すアプリです。</p>
<p>基本はその場でパシャリと写真撮るだけの使い方です。簡単なメモが追記できるので、「駅の南口出てスグのところ」みたいな場所を思い出すヒントをかけます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140812/20140812212648.png" alt="f:id:himaratsu:20140812212648p:plain" title="f:id:himaratsu:20140812212648p:plain" class="hatena-fotolife" itemprop="image" width="250" style="border:1px solid #ccc"></span></p>
<p>また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/foursquare">foursquare</a>の情報を使っていて、写真の<a class="keyword" href="http://d.hatena.ne.jp/keyword/GPS">GPS</a>情報から自動でお店の詳細情報を取得したりします。</p>
<h2>つくった背景</h2>
<p>4月に違う街に引っ越しました。引っ越し先の周りは美味しそうなお店が多くて「今度来よう!」と良く思うのですが、すぐ忘れてしまいます。<br />
休日、どこかご飯食べに行こう〜と思ったときには当然思い出せず、いつも行ってるお店に行ってしまいます。</p>
<p>簡単に残しておいて、サッと一覧視できるようなアプリが欲しい。そう思って作りました。</p>
<h2>似たアプリは既にあった</h2>
<p>「あとで行く」系のアプリは既にいくつかありました。</p>
<ul>
<li><a href="http://www.shopcard.me/ja">ShopCard.me</a></li>
<li><a href="http://atodeiku.com/global">あとで行く beta</a></li>
<li><a href="http://www.golater.me/jp/index.php">Go Later</a></li>
</ul>
<p>どれも良くできてるのですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Evernote">Evernote</a>や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA">はてな</a>との連携は特にやりたくなくて、シンプルに登録できてサクサク見返せるものはなかったです。</p>
<p>あと関係ないですが Go Later を使ってみようと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>を開くと「お前」と呼ばれました。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140812/20140812212352.jpg" alt="f:id:himaratsu:20140812212352j:plain" title="f:id:himaratsu:20140812212352j:plain" class="hatena-fotolife" itemprop="image" width="250" style="border:1px solid #ccc"></span></p>
<h3>なにができるか?</h3>
<p>Go Memoでは、記録した場所は一覧表示とマップ表示で確認できます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140812/20140812212648.png" alt="f:id:himaratsu:20140812212648p:plain" title="f:id:himaratsu:20140812212648p:plain" class="hatena-fotolife" itemprop="image" width="250" style="border:1px solid #ccc"></span>
<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140812/20140812212812.png" alt="f:id:himaratsu:20140812212812p:plain" title="f:id:himaratsu:20140812212812p:plain" class="hatena-fotolife" itemprop="image" width="250" style="border:1px solid #ccc"></span></p>
<p>場所の詳細画面はこんな感じで、情報をスッキリまとめました。<br />
見やすくてなかなか気に入ってます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140812/20140812212852.png" alt="f:id:himaratsu:20140812212852p:plain" title="f:id:himaratsu:20140812212852p:plain" class="hatena-fotolife" itemprop="image" width="250" style="border:1px solid #ccc"></span></p>
<h3>手描きの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a></h3>
<p>機能は説明いらないくらいシンプルなので、起動時には利用シーンを見せることにしました。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140812/20140812220547.png" alt="f:id:himaratsu:20140812220547p:plain" title="f:id:himaratsu:20140812220547p:plain" class="hatena-fotolife" itemprop="image" width="250" style="border:1px solid #ccc"></span></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>って適当にスキップされがちなので、見てもらうためにちょっと特別感を出そうと手描きイラストにしました(友人に描いてもらいました)。<br />
とても素敵な感じになってるのでぜひ見てみてください!</p>
<h3>さいごに</h3>
<p>自分の欲しいものだし、継続的に良くしていきたいなと思ってます。</p>
<ul>
<li>お店の近くに来たときに通知</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%A9%A4%D9%A5%ED%A5%B0">食べログ</a>とかの情報から登録(友達に教えてもらうシーン想定)</li>
</ul>
<p>などを実装していく予定です。<br />
何かこういう機能が欲しい、というご要望があればアプリ内の「ご意見・ご要望」フォームから頂けると嬉しいです。</p>
<h3>それでは</h3>
<p>「あとで行く」ためのアプリ Go Memo、良ければ使ってみてください◎<br />
<a href="https://itunes.apple.com/jp/app/id903841654?mt=8">https://itunes.apple.com/jp/app/id903841654?mt=8</a></p>
himaratsu
iOSアプリ開発で上手に色を操るための設定まとめ
hatenablog://entry/12921228815729416436
2014-08-03T20:25:40+09:00
2022-02-24T19:50:50+09:00 最近エンジニアでもデザイン頑張ろう系のエントリをよく目にします。
<p>最近エンジニアでもデザイン頑張ろう系のエントリをよく目にします。</p>
<ul>
<li><a href="http://rejasupotaro.github.io/2014/06/04/48.html">0から学ぶアプリの配色 | Rejasupoem</a></li>
<li><a href="https://speakerdeck.com/ken_c_lo/webenziniafalsetamefalsewebsabisudezainshi-jian-jiang-zuo">WebエンジニアのためのWebサービスデザイン実践講座 | Spearker Docks</a></li>
</ul>
<p>これには同感で、特にアプリエンジニアはデザインも理解していくべきだと思ってます。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>で色を簡単に扱える準備をしたので、その内容をまとめます。</p>
<h1>1.<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a>に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3">プラグイン</a>を入れる</h1>
<h3>Hex Color Picker</h3>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140802/20140802193508.png" alt="f:id:himaratsu:20140802193508p:plain" title="f:id:himaratsu:20140802193508p:plain" class="hatena-fotolife" itemprop="image" width="350px" style="border:solid 2px #ddd; padding:2px"></span></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a>のカラーピッカーにHexタブを追加できる<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> Pluginです。<br />
色の指定を<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>のように16進数で行えて便利ですね。</p>
<h4>導入方法</h4>
<ul>
<li>1.公式サイトからダウンロード
<ul>
<li><a href="http://wafflesoftware.net/hexpicker/">http://wafflesoftware.net/hexpicker/</a></li>
</ul>
</li>
<li>2.Finder -> 移動メニュー で optionキーを押して「ライブラリ」へ移動</li>
<li>3.ColorPickers <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リに<code>HexColorPicker.colorPicker</code>を追加</li>
<li>4.<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a>を再起動</li>
</ul>
<h3>OMColorSense</h3>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140803/20140803010234.png" alt="f:id:himaratsu:20140803010234p:plain" title="f:id:himaratsu:20140803010234p:plain" class="hatena-fotolife" itemprop="image" style="border:2px solid #ddd; padding:2px"></span></p>
<p>エディタ上のUIColorをビジュアライズしてくれる<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> Pluginです。<br />
フォーカスがあたるとカラーが出て良い感じです。</p>
<h4>導入手順</h4>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a>向けパッケージ管理ツール「Alcatraz」を用いると簡単です。</p>
<ul>
<li>1.Alcatraz をインストールする(まだの場合)
<ul>
<li><a href="http://alcatraz.io/">http://alcatraz.io/</a> からダウンロード</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a>を再起動する</li>
</ul>
</li>
<li>2.Window > Package Manager を開く</li>
<li>3.<code>OMColorSense</code> をインストールする</li>
<li>4.<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a>を再起動する</li>
</ul>
<h1>2.コードで色を指定しやすくする</h1>
<h3>UIColorのカテゴリを作る</h3>
<p>こんな感じで定義して使ってます。</p>
<p><strong>UIColor+Hex.h</strong></p>
<pre class="code lang-objc" data-lang="objc" data-unlink><span class="synIdentifier">+ </span>(UIColor*)colorWithHexString:(<span class="synType">NSString</span> *)hex;
<span class="synIdentifier">+ </span>(UIColor*)colorWithHexString:(<span class="synType">NSString</span> *)hex alpha:(<span class="synType">CGFloat</span>)a;
</pre>
<p><strong>UIColor+Hex.m</strong></p>
<pre class="code lang-objc" data-lang="objc" data-unlink><span class="synIdentifier">+ </span>(UIColor*)colorWithHexString:(<span class="synType">NSString</span> *)hex {
<span class="synStatement">return</span> [<span class="synStatement">self</span> colorWithHexString:hex alpha:<span class="synConstant">1.0</span>];
}
<span class="synIdentifier">+ </span>(UIColor*)colorWithHexString:(<span class="synType">NSString</span> *)hex alpha:(<span class="synType">CGFloat</span>)a {
<span class="synType">NSScanner</span> *colorScanner = [NSScanner scannerWithString:hex];
<span class="synType">unsigned</span> <span class="synType">int</span> color;
<span class="synStatement">if</span> (![colorScanner scanHexInt:&color]) <span class="synStatement">return</span> <span class="synConstant">nil</span>;
<span class="synType">CGFloat</span> r = ((color & <span class="synConstant">0xFF0000</span>) >> <span class="synConstant">16</span>)/<span class="synConstant">255.0f</span>;
<span class="synType">CGFloat</span> g = ((color & <span class="synConstant">0x00FF00</span>) >> <span class="synConstant">8</span>) /<span class="synConstant">255.0f</span>;
<span class="synType">CGFloat</span> b = (color & <span class="synConstant">0x0000FF</span>) /<span class="synConstant">255.0f</span>;
<span class="synStatement">return</span> [UIColor colorWithRed:r green:g blue:b alpha:a];
}
</pre>
<p><strong>使い方</strong></p>
<pre class="code lang-objc" data-lang="objc" data-unlink><span class="synComment">// UIColor を使いたい場所で</span>
myLabel.textColor = [UIColor colorWithHex:<span class="synConstant">@"ebebeb"</span>];
</pre>
<h3>頻繁に使う色は定義しておく</h3>
<p>アプリのテーマカラーなど、頻出の色は #define で定義しておきます。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink><span class="synPreProc">#define kDefaultTextColor [UIColor colorWithRed:</span><span class="synConstant">70</span><span class="synPreProc">/</span><span class="synConstant">255.0</span><span class="synPreProc"> green:</span><span class="synConstant">171</span><span class="synPreProc">/</span><span class="synConstant">255.0</span><span class="synPreProc"> blue:</span><span class="synConstant">235</span><span class="synPreProc">/</span><span class="synConstant">255.0</span><span class="synPreProc"> alpha:</span><span class="synConstant">1.0</span><span class="synPreProc">]</span>
</pre>
<p><strong>使い方</strong></p>
<pre class="code lang-objc" data-lang="objc" data-unlink>myLabel.textColor = kDefaultTextColor;
</pre>
<h1>3.おまけ:その他のツール</h1>
<h3>ディスプレイに表示されてる色を取得する(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Mac">Mac</a>で)</h3>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140803/20140803004634.png" alt="f:id:himaratsu:20140803004634p:plain" title="f:id:himaratsu:20140803004634p:plain" class="hatena-fotolife" itemprop="image" width="400px"></span></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Mac">Mac</a> には <strong>DigitalColor Meter</strong> というツールが標準で入っており、これを使うとRGB値が簡単に取得できます。「あ、この色良さそう」と思ったときに起動してRGBをメモしておくと良いです。</p>
<p>DigitalColor Meter はユーティリティの中にあります。</p>
<h3>Webページで使われている色を取得する(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>拡張で)</h3>
<p><a href="https://chrome.google.com/webstore/detail/pendule/gbkffbkamcejhkcaocmkdeiiccpmjfdi">Pendule</a> という<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome">Chrome</a>拡張でそのページで使用されているカラーが取得できます。<br />
例えば<a class="keyword" href="http://d.hatena.ne.jp/keyword/Facebook">Facebook</a>のTOPページを解析した場合、以下のようなリストにしてくれます。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140803/20140803010728.png" alt="f:id:himaratsu:20140803010728p:plain" title="f:id:himaratsu:20140803010728p:plain" class="hatena-fotolife" itemprop="image" style="border:solid 2px #ddd; padding:2px" width="400px"></span></p>
<p>使い方は簡単で、対象のページを開いて <code>Pendule > Show used colors</code> するだけです。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140803/20140803004906.png" alt="f:id:himaratsu:20140803004906p:plain" title="f:id:himaratsu:20140803004906p:plain" class="hatena-fotolife" itemprop="image" style="border:solid 2px #ddd; padding:2px" width="400px"></span></p>
<p>「このサイトのようなカラーテーマにしたい」という時に重宝するツールです。<br />
Pendule のダウンロードはここからできます:</p>
<ul>
<li><a href="https://chrome.google.com/webstore/detail/pendule/gbkffbkamcejhkcaocmkdeiiccpmjfdi">Pendule | Chrome Web Store</a></li>
</ul>
<p>--</p>
<p>以上です。<br />
ツールの導入は最初は時間がかかってしまいますが、今回紹介したものはヘビーに使えて本当に便利なものばかりなのでぜひ試してみてください。</p>
<h1>参考リンク</h1>
<ul>
<li><a href="http://paranishian.hateblo.jp/entry/xcode/hexcolor">Interface Builderで16進の色コード(Hex Color)を使えるようにするプラグインを導入する</a></li>
<li><a href="http://dev.classmethod.jp/smartphone/ios-tips-2/">iOS Tips #2 16進数でUIColorを生成する</a></li>
<li><a href="http://phpspot.org/blog/archives/2012/04/webchromependul.html">WEB開発者はインストール必須のChrome拡張「Pendule」</a></li>
</ul>
<h1>関連書籍</h1>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4844335065?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/41vwvhVleCL._SL500_.jpg" class="hatena-asin-detail-image" alt="iOS 7デザインスタンダード 最新のフラットデザインに対応-iPhoneに最適なUI・UXを徹底的に解説!" title="iOS 7デザインスタンダード 最新のフラットデザインに対応-iPhoneに最適なUI・UXを徹底的に解説!"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4844335065?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">iOS 7デザインスタンダード 最新のフラットデザインに対応-iPhoneに最適なUI・UXを徹底的に解説!</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%B2%AE%CC%EE%20%C7%EE%BE%CF" class="keyword">荻野 博章</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%D7%A5%EC%A5%B9">インプレス</a></li></ul><a href="https://www.amazon.co.jp/dp/4844335065?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div>
<div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/4798040010?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/410u-UHQqKL._SL500_.jpg" class="hatena-asin-detail-image" alt="iOSフラットデザインの作法Appleガイドラインの理解とFlat UIの実践" title="iOSフラットデザインの作法Appleガイドラインの理解とFlat UIの実践"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/4798040010?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">iOSフラットデザインの作法Appleガイドラインの理解とFlat UIの実践</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C0%F4%CB%DC%20%CD%A5%B5%B1" class="keyword">泉本 優輝</a>,<a href="http://d.hatena.ne.jp/keyword/%B5%C8%C3%DD%20%CE%CB" class="keyword">吉竹 遼</a>,<a href="http://d.hatena.ne.jp/keyword/%C4%C5%BC%E9%20%CD%A5" class="keyword">津守 優</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%A8%CF%C2%A5%B7%A5%B9%A5%C6%A5%E0">秀和システム</a></li></ul><a href="https://www.amazon.co.jp/dp/4798040010?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
<p>自分でデザインも考えてみたいエンジニアの方におすすめです。</p>
himaratsu
SwiftでTiqav APIを叩くビューワアプリを100行でつくったよ
hatenablog://entry/12921228815725514915
2014-06-04T20:40:56+09:00
2022-02-24T19:50:49+09:00 2015/03/30 追記 記載しているコードは古くて動かない可能性があります。 最新の環境で動くコードは以下に置いてあります: https://github.com/himaratsu/SwiftTiqavViewer -- 以下の記事を読んで触発されてつくってみました。 SwiftのRSS Readerを100行で作ったよ - Qiita
<p><strong>2015/03/30 追記</strong><br />
記載しているコードは古くて動かない可能性があります。<br />
最新の環境で動くコードは以下に置いてあります:
<a href="https://github.com/himaratsu/SwiftTiqavViewer">https://github.com/himaratsu/SwiftTiqavViewer</a></p>
<p>--</p>
<p>以下の記事を読んで触発されてつくってみました。</p>
<ul>
<li><a href="http://qiita.com/susieyy/items/749c4ac5d82d765c12c6">SwiftのRSS Readerを100行で作ったよ - Qiita</a></li>
</ul>
<h2>つくったもの</h2>
<p><strong>Tiqav viewer</strong></p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140604/20140604190931.png" alt="f:id:himaratsu:20140604190931p:plain" title="f:id:himaratsu:20140604190931p:plain" class="hatena-fotolife" itemprop="image" width="300px"></span></p>
<h2>Tiqavとは</h2>
<p><a href="http://tiqav.com/">「レス画像検索No.1/画像会話なら ちくわぶ」</a></p>
<p>言葉に応じた画像を検索できるサービスです。<br />
<a href="http://dev.tiqav.com/">登録されている画像を返すAPIが公開されている</a>のでSwiftで使ってみました。</p>
<h2>アプリの概要</h2>
<ul>
<li>Storyboard 使用</li>
<li>NSURLConnection で tiqav <a class="keyword" href="http://d.hatena.ne.jp/keyword/api">api</a> を叩いて結果をパース</li>
<li>UITableView (+Custome Cell) に結果を表示</li>
</ul>
<h2>ファイルの構成</h2>
<ul>
<li>AppDelegate.swift
<ul>
<li>自動生成のまま</li>
</ul>
</li>
<li><strong>ViewController.swift</strong>
<ul>
<li><strong>以下で紹介する</strong></li>
</ul>
</li>
<li>Main.storyboard
<ul>
<li>ViewContoller.swiftにUITableView, UITableViewCellを追加</li>
</ul>
</li>
<li>TiqavCell.swift
<ul>
<li>カスタムUITableViewCell. IBOutletをもたせただけ</li>
</ul>
</li>
</ul>
<h2>コードの要点</h2>
<h3>通信 (NSURLConnection)</h3>
<p>NSURLConnectionを使ってWebAPIにアクセスする方法です。</p>
<pre class="code lang-objc" data-lang="objc" data-unlink>func <span class="synIdentifier">reload</span>() {
<span class="synComment">// Thanks to tiqav api! ( http://dev.tiqav.com/ )</span>
let URL = <span class="synIdentifier">NSURL</span>(string: <span class="synConstant">"http://api.tiqav.com/search/random.json"</span>)
let req = <span class="synIdentifier">NSURLRequest</span>(URL: URL)
let connection: NSURLConnection = <span class="synIdentifier">NSURLConnection</span>(request: req, delegate: <span class="synStatement">self</span>, startImmediately: <span class="synConstant">false</span>)
<span class="synComment">// NSURLConnectionを使ってアクセス</span>
NSURLConnection.<span class="synIdentifier">sendAsynchronousRequest</span>(Req,
queue: NSOperationQueue.<span class="synIdentifier">mainQueue</span>(),
completionHandler: <span class="synStatement">self</span>.fetchResponse)
}
<span class="synComment">// responseを処理する</span>
func <span class="synIdentifier">fetchResponse</span>(res: NSURLResponse!, data: NSData!, error: NSError!) {
<span class="synComment">// responseをjsonに変換</span>
let json: NSArray = NSJSONSerialization.<span class="synIdentifier">JSONObjectWithData</span>(data, options: NSJSONReadingOptions.AllowFragments, error: <span class="synConstant">nil</span>) as NSArray
tiqavs = []
<span class="synStatement">for</span> img<span class="synStatement"> in </span>json {
let imgId = img[<span class="synConstant">"id"</span>] as String
let ext = img[<span class="synConstant">"ext"</span>] as String
let imageUrl = (baseUrl + imgId + <span class="synConstant">"."</span> + ext) as String
tiqavs.<span class="synIdentifier">append</span>(imageUrl)
}
<span class="synComment">// tableviewの更新</span>
<span class="synIdentifier">dispatch_async</span>(<span class="synIdentifier">dispatch_get_main_queue</span>(), <span class="synError">{</span>
<span class="synStatement">self</span>.tableView.<span class="synIdentifier">reloadData</span>()
}<span class="synError">)</span>
}
</pre>
<p><code>NSJSONSerialization.JSONObjectWithData</code> は <code>AnyObject!</code> を返すので、<code>as NSArray</code> などとして型を指定する必要があります。<br />
本来であれば array か dictionary かを判定して型を指定すれば良いはずです。</p>
<p>ここで用いている<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>のレスポンス例は以下のような感じです。</p>
<pre class="code bash" data-lang="bash" data-unlink>({
ext = jpg;
height = 300;
id = 1b8;
"source_url" = "http://jan.2chan.net/jun/b/src/1260209767367.jpg";
width = 400;
})</pre>
<h3>非同期での画像の読み込み</h3>
<p>以下のページの1つ目のやり方をswiftで実装してます。</p>
<ul>
<li><a href="http://qiita.com/EntreGulss/items/d7d9fb5d0b93eb509d43">URLから画像を非同期に読み込む3種類の実装 - Qiita</a></li>
</ul>
<pre class="code lang-objc" data-lang="objc" data-unlink>var q_global: dispatch_queue_t = <span class="synIdentifier">dispatch_get_global_queue</span>(DISPATCH_QUEUE_PRIORITY_DEFAULT, <span class="synConstant">0</span>);
var q_main: dispatch_queue_t = <span class="synIdentifier">dispatch_get_main_queue</span>();
<span class="synComment">// imageUrl に画像のURLが入っている</span>
<span class="synComment">// 非同期でimageUrlの内容を取得</span>
<span class="synIdentifier">dispatch_async</span>(q_global, <span class="synError">{</span>
var imageURL: NSURL = NSURL.<span class="synIdentifier">URLWithString</span>(imageUrl)
var imageData: NSData = <span class="synIdentifier">NSData</span>(contentsOfURL: imageURL)
var image: UIImage = <span class="synIdentifier">UIImage</span>(data: imageData)
<span class="synComment">// 更新はmain threadで</span>
<span class="synIdentifier">dispatch_async</span>(q_main, <span class="synError">{</span>
cell.tiqavImageView.image = image;
cell.<span class="synIdentifier">layoutSubviews</span>()
}<span class="synError">)</span>
}<span class="synError">)</span>
</pre>
<p>画像を非同期で取得してメインスレッドでUI更新。<br />
GCDはそのまま素直に使えるようでスンナリ書けました。</p>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/delegate">delegate</a> の実装宣言</h3>
<pre class="code lang-objc" data-lang="objc" data-unlink>class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, NSURLConnectionDelegate {
...
}
</pre>
<p>こんな感じで書きます。<br />
UITableViewDataSource, UITableViewDelegate の接続は今回はStoryboardでやってます。</p>
<h2>コード全文</h2>
<h4>ViewController.swift</h4>
<pre class="code lang-objc" data-lang="objc" data-unlink>import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, NSURLConnectionDelegate {
@IBOutlet var tableView : UITableView!
let baseUrl = <span class="synConstant">"http://img.tiqav.com/"</span>
var tiqavs = [String]()
override func <span class="synIdentifier">viewDidLoad</span>() {
<span class="synStatement">super</span>.<span class="synIdentifier">viewDidLoad</span>()
<span class="synStatement">self</span>.title = <span class="synConstant">"tiqav images"</span>
<span class="synStatement">self</span>.<span class="synIdentifier">reload</span>()
}
func <span class="synIdentifier">reload</span>() {
<span class="synComment">// Thanks to tiqav api! ( http://dev.tiqav.com/ )</span>
let URL = <span class="synIdentifier">NSURL</span>(string: <span class="synConstant">"http://api.tiqav.com/search/random.json"</span>)
let Req = <span class="synIdentifier">NSURLRequest</span>(URL: URL)
let connection: NSURLConnection = <span class="synIdentifier">NSURLConnection</span>(request: Req, delegate: <span class="synStatement">self</span>, startImmediately: <span class="synConstant">false</span>)
NSURLConnection.<span class="synIdentifier">sendAsynchronousRequest</span>(Req,
queue: NSOperationQueue.<span class="synIdentifier">mainQueue</span>(),
completionHandler: <span class="synStatement">self</span>.fetchResponse)
}
func <span class="synIdentifier">fetchResponse</span>(res: NSURLResponse!, data: NSData!, error: NSError!) {
let json: NSArray = NSJSONSerialization.<span class="synIdentifier">JSONObjectWithData</span>(data, options: NSJSONReadingOptions.AllowFragments, error: <span class="synConstant">nil</span>) as NSArray
tiqavs = [String]()
<span class="synStatement">for</span> img<span class="synStatement"> in </span>json {
let imgId = img[<span class="synConstant">"id"</span>] as String
let ext = img[<span class="synConstant">"ext"</span>] as String
let imageUrl = (baseUrl + imgId + <span class="synConstant">"."</span> + ext) as String
tiqavs.<span class="synIdentifier">append</span>(imageUrl)
}
<span class="synIdentifier">dispatch_async</span>(<span class="synIdentifier">dispatch_get_main_queue</span>(), <span class="synError">{</span>
<span class="synStatement">self</span>.tableView.<span class="synIdentifier">reloadData</span>()
}<span class="synError">)</span>
}
func <span class="synIdentifier">tableView</span>(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> <span class="synType">CGFloat</span> {
<span class="synStatement">return</span> <span class="synConstant">120</span>
}
func <span class="synIdentifier">tableView</span>(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
<span class="synStatement">return</span> tiqavs.count
}
func <span class="synIdentifier">tableView</span>(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: TiqavCell = <span class="synStatement">self</span>.tableView.<span class="synIdentifier">dequeueReusableCellWithIdentifier</span>(<span class="synConstant">"Cell"</span>) as TiqavCell
var imageUrl = tiqavs[indexPath.row] as String
cell.tiqavUrlLabel.text = imageUrl;
cell.tiqavImageView.image = <span class="synConstant">nil</span>;
var q_global: dispatch_queue_t = <span class="synIdentifier">dispatch_get_global_queue</span>(DISPATCH_QUEUE_PRIORITY_DEFAULT, <span class="synConstant">0</span>);
var q_main: dispatch_queue_t = <span class="synIdentifier">dispatch_get_main_queue</span>();
<span class="synIdentifier">dispatch_async</span>(q_global, <span class="synError">{</span>
var imageURL: NSURL = NSURL.<span class="synIdentifier">URLWithString</span>(imageUrl)
var imageData: NSData = <span class="synIdentifier">NSData</span>(contentsOfURL: imageURL)
var image: UIImage = <span class="synIdentifier">UIImage</span>(data: imageData)
<span class="synIdentifier">dispatch_async</span>(q_main, <span class="synError">{</span>
cell.tiqavImageView.image = image;
cell.<span class="synIdentifier">layoutSubviews</span>()
}<span class="synError">)</span>
}<span class="synError">)</span>
<span class="synStatement">return</span> cell;
}
func <span class="synIdentifier">tableView</span>(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var text: String = tiqavs[indexPath.row]
<span class="synComment">// show alert</span>
let alert = <span class="synIdentifier">UIAlertController</span>(title: <span class="synConstant">"taped"</span>, message: text, preferredStyle: .Alert)
alert.<span class="synIdentifier">addAction</span>(<span class="synIdentifier">UIAlertAction</span>(title: <span class="synConstant">"close"</span>, style: .Default, handler: <span class="synConstant">nil</span>))
<span class="synStatement">self</span>.<span class="synIdentifier">presentViewController</span>(alert, animated: <span class="synConstant">true</span>, completion: <span class="synConstant">nil</span>)
}
@IBAction func <span class="synIdentifier">reloadBtnTouched</span>(sender : AnyObject) {
<span class="synStatement">self</span>.<span class="synIdentifier">reload</span>()
<span class="synStatement">self</span>.tableView.<span class="synIdentifier">scrollRectToVisible</span>(<span class="synType">CGRect</span>(x:<span class="synConstant">0</span> , y: <span class="synConstant">0</span>, width: <span class="synConstant">1</span>,height:<span class="synConstant">1</span>), animated: <span class="synConstant">true</span>)
}
}
</pre>
<h4>TiqavCell.swift</h4>
<pre class="code lang-objc" data-lang="objc" data-unlink>import UIKit
class TiqavCell: UITableViewCell {
@IBOutlet var tiqavImageView : UIImageView!
@IBOutlet var tiqavUrlLabel : UILabel!
override func <span class="synIdentifier">awakeFromNib</span>() {
<span class="synStatement">super</span>.<span class="synIdentifier">awakeFromNib</span>()
tiqavUrlLabel.backgroundColor = <span class="synIdentifier">UIColor</span>(red: <span class="synConstant">0.95</span>, green: <span class="synConstant">0.95</span>, blue: <span class="synConstant">0.95</span>, alpha: <span class="synConstant">0.8</span>)
}
}
</pre>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a></h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a>にあげました</p>
<ul>
<li><a href="https://github.com/himaratsu/SwiftTiqavViewer">https://github.com/himaratsu/SwiftTiqavViewer</a></li>
</ul>
<h2>ここまでのSwift</h2>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a>の補完がちゃんと効けば気持ちよく書けそう
<ul>
<li>インデキシングに時間がかかってるだけという説を信じてる</li>
</ul>
</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Objective-C">Objective-C</a>とあまり変わらないので慣れると書きやすい</li>
<li>! と ? の仕様が分かってない</li>
<li><code>heightForRowAtIndexPath</code> でstaticのcellを作って高さを返すのが何故かできない</li>
<li>dispatchとか使っての非同期処理はそのまま書けそう</li>
</ul>
<h2>まとめ</h2>
<p>最初の記法だけ覚えれば<a class="keyword" href="http://d.hatena.ne.jp/keyword/Objective-C">Objective-C</a>の知識でほぼ書けそうです。<br />
Swift各地で盛り上がっててなんか祭り感あって楽しいです。</p>
<h2>関連書籍</h2>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/dp/477416366X?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="hatena-asin-detail-image-link" target="_blank" rel="noopener"><img src="https://m.media-amazon.com/images/I/51PjpAUHZBL._SL500_.jpg" class="hatena-asin-detail-image" alt="GitHub実践入門 ~Pull Requestによる開発の変革 (WEB+DB PRESS plus)" title="GitHub実践入門 ~Pull Requestによる開発の変革 (WEB+DB PRESS plus)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/dp/477416366X?tag=samura1-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener">GitHub実践入門 ~Pull Requestによる開発の変革 (WEB+DB PRESS plus)</a></p><ul class="hatena-asin-detail-meta"><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C2%E7%C4%CD%20%B9%B0%B5%AD" class="keyword">大塚 弘記</a></li><li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%BB%BD%D1%C9%BE%CF%C0%BC%D2">技術評論社</a></li></ul><a href="https://www.amazon.co.jp/dp/477416366X?tag=samura1-22&linkCode=ogi&th=1&psc=1" class="asin-detail-buy" target="_blank" rel="noopener">Amazon</a></div></div></p>
himaratsu
第7回はDeNA開催! #potatotips で発表されたiOSのtipsまとめ
hatenablog://entry/12921228815724223107
2014-05-15T22:46:22+09:00
2022-02-24T19:50:56+09:00 第7回となるクックパッドさんの #potatotips に参加させて頂きました。 今回は株式会社DeNA@渋谷ヒカリエでの開催でした。 https://github.com/potatotips/potatotips/wiki/Potatotips-7
<p>第7回となる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%C3%A5%AF%A5%D1%A5%C3%A5%C9">クックパッド</a>さんの #potatotips に参加させて頂きました。<br />
今回は株式会社<a class="keyword" href="http://d.hatena.ne.jp/keyword/DeNA">DeNA</a>@<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%C2%C3%AB%A5%D2%A5%AB%A5%EA%A5%A8">渋谷ヒカリエ</a>での開催でした。
<a href="https://github.com/potatotips/potatotips/wiki/Potatotips-7">https://github.com/potatotips/potatotips/wiki/Potatotips-7</a></p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20140515/20140515223353.jpg" alt="f:id:himaratsu:20140515223353j:plain" title="f:id:himaratsu:20140515223353j:plain" class="hatena-fotolife" itemprop="image"></span></p>
<p>potatotipsは発表者だけが参加できる、持ち時間1人5分のtips共有会です。<br />
7回目となる今回も濃厚なtipsが多く発表された会となりました。</p>
<p>そんな第7回で発表された11個の<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>のtipsをまとめます!</p>
<p>※<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>のtipsはこちらをご参考ください<br />
→ <a href="http://sys1yagi.com/blog/2014/05/15/potatotips-07/">DeNA開催! #potatotips 7に参加してきました。 Android tips 11個まとめ</a></p>
<h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> tips</h1>
<h3>ICTurorialOverlay</h3>
<ul>
<li><a href="https://twitter.com/i110">@i110</a>さん</li>
<li>プロダクトにはオーバーレイ型の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>を作りがち</li>
<li>透過のviewを張るだけなら良いが、フォーカス領域だけ穴をあけたい場合がある</li>
<li>そんな時に便利なライブラリを作った!</li>
<li><a href="https://github.com/i110/ICTutorialOverlay">ICTurorialOverlay | GitHub</a>
<ul>
<li>穴を開ける位置やタップ時の処理を自由にカスタマイズできる</li>
</ul>
</li>
<li><iframe src="http://www.slideshare.net/slideshow/embed_code/34732974" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px 1px 0; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/ichitonagata/ictutorialoverlay-a-utility-for-making-overlay-tutorial" title="ICTutorialOverlay : A utility for making "Overlay Tutorial"" target="_blank">ICTutorialOverlay : A utility for making "Overlay Tutorial"</a> </strong> from <strong><a href="http://www.slideshare.net/ichitonagata" target="_blank">Ichito Nagata</a></strong> </div></li>
</ul>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> Tips よせあつめ</h3>
<ul>
<li><a href="https://twitter.com/sea__mountain">@sea__mountain</a>さん</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a> 3つのtips
<ul>
<li>フォントサイズやカラーテーマを変える
<ul>
<li>カラーテーマは追加もできる(<a href="https://github.com/tursunovic/xcode-themes">Xcode Themes | GitHub</a>)</li>
</ul>
</li>
<li>リファレンスを爆速で起動する</li>
<li>複数ver.の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Xcode">Xcode</a>を扱う方法</li>
</ul>
</li>
<li><a href="http://sea-mountain.hatenablog.jp/entry/2014/05/15/193445">potatotips #7 で発表してきました - うみやま亭</a></li>
<li><script async class="speakerdeck-embed" data-id="9ea31150bdbc0131ba3016b66683ddab" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h3>笑顔があつまる
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%EC%A1%BC%A5%B7%A5%E7%A5%F3">インスタレーション</a> Smile:D</h3>
<ul>
<li><a href="https://twitter.com/okitsu">@okitsu</a> さん</li>
<li>こういうものを作った
<ul>
<li><iframe width="560" height="315" src="//www.youtube.com/embed/cFRNt1vFdSo" frameborder="0" allowfullscreen></iframe></li>
</ul>
</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>の笑顔認識, Multipeer Connectivity などを使った</li>
<li>ふわっとした動きには <a href="https://github.com/C4Framework/C4iOS">C4Framework</a> を使っている</li>
<li><script async class="speakerdeck-embed" data-id="c5044db0be47013191842a9c30b9cc56" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h3>UIToolbarの同時タッチを防ぐ</h3>
<ul>
<li><a href="https://twitter.com/sonson_twit">@sonson_twit</a> さん</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A1%BC%A5%EB%A5%D0%A1%BC">ツールバー</a>のボタンを押しながらNavConのジェスチャ発動 -> 階層が壊れてしまう話</li>
<li>対策1) UIBarButtonItemで処理 →この方法は苦しい</li>
<li>対策2) UIToolBarにジェスチャをつける →これが汎用性などの観点で良さそう
<ul>
<li>touchesBegan などでうまくハンドリングしてやる</li>
</ul>
</li>
<li><iframe src="http://www.slideshare.net/slideshow/embed_code/34725745" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px 1px 0; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/yoshidayuichi1/presentation-34725745" title="UIToolbarの同時タッチを防ぐ" target="_blank">UIToolbarの同時タッチを防ぐ</a> </strong> from <strong><a href="http://www.slideshare.net/yoshidayuichi1" target="_blank">Yuichi Yoshida</a></strong> </div></li>
</ul>
<h3>UIAppearanceつらい</h3>
<ul>
<li><a href="https://twitter.com/feb19">@feb19</a>さん</li>
<li>UIAppearance とは、stylesheet的に見た目を一気に変えられるアレ</li>
<li>しかし、UIDatePicker だけはなぜか変更されない</li>
<li>runtime attribute に設定すれば一応変えることはできた
<ul>
<li>が、挙動が怪しかったりfont-familyは変えられなかったりする</li>
<li>何か知ってる人がいたら教えて欲しい</li>
</ul>
</li>
<li><iframe src="http://www.slideshare.net/slideshow/embed_code/34719228" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px 1px 0; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/feb19/ui-appearance" title="Ui Appearanceでハマった話" target="_blank">Ui Appearanceでハマった話</a> </strong> from <strong><a href="http://www.slideshare.net/feb19" target="_blank">Nobuhiro Takahashi</a></strong> </div></li>
</ul>
<h3>だいすきStoryboard</h3>
<ul>
<li><a href="https://twitter.com/kenmaz">@kenmaz</a>さん</li>
<li>最近マンガBOXの中身について記事を書いた
<ul>
<li><a href="https://codeiq.jp/magazine/2014/05/9946/">DeNA中の人が解説する「マンガボックス」システム構成とiOSアプリの内部構成</a></li>
</ul>
</li>
<li>そこで書ききれなかった話を今日する
<ul>
<li>UIパーツの定義をうまくやる方法</li>
<li>アプリ起動時に処理待ちをする方法(migration待ちの時など)</li>
<li>Storyboardを分割するということ</li>
</ul>
</li>
<li>CodeIQの記事も含めて、Container Viewの使い方が勉強になりました</li>
<li><iframe src="http://www.slideshare.net/slideshow/embed_code/34726644" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px 1px 0; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/kenmaz/storyboard-34726644" title="だいすきStoryboard - #potatotips (iOS/Android開発Tips共有会) 第7回" target="_blank">だいすきStoryboard - #potatotips (iOS/Android開発Tips共有会) 第7回</a> </strong> from <strong><a href="http://www.slideshare.net/kenmaz" target="_blank">Kentaro Matsumae</a></strong> </div></li>
</ul>
<h3>デザイナーと仲良くするtips</h3>
<ul>
<li><a href="https://twitter.com/hrk_ys">@hrk_ys</a>さん</li>
<li>CollectionViewなどで、2xNか3xNどちらが良いか?を決めるとき
<ul>
<li>ボタンをつけてやって、アプリで切り替えられるようにする</li>
</ul>
</li>
<li>アニメーションのdurationを細かくチューニングしたいとき
<ul>
<li>Tweaks という<a class="keyword" href="http://d.hatena.ne.jp/keyword/Facebook">Facebook</a>製のライブラリがある
<ul>
<li><a href="https://github.com/facebook/Tweaks">Tweaks | GitHub</a></li>
</ul>
</li>
<li>秒数設定用の設定画面をシェイクして出せるなど</li>
</ul>
</li>
</ul>
<h3>本気で手を抜く<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Analytics">Google Analytics</a></h3>
<ul>
<li><a href="https://twitter.com/jeffsuke">@jeffsuke</a>さん</li>
<li>プロジェクトに<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Analytics">Google Analytics</a>を導入した話</li>
<li>該当箇所に単純につっこむのでは、コードが散らかってしまって良くない</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Aspect">Aspect</a> を使うと簡単に書ける!
<ul>
<li><a href="https://github.com/steipete/Aspects">Aspect | GitHub</a></li>
</ul>
</li>
<li>keyを <code>const.h</code> などにまとめておけば、どんなログを取ってるか整理しやすい</li>
</ul>
<h3>agvtool で超かっこよくバージョニングできますか?</h3>
<ul>
<li><a href="https://twitter.com/tokorom">@tokorom</a>さん</li>
<li>agvtool とは、プロジェクトのバージョニングをいい感じに操作できるコマンド
<ul>
<li><a href="http://cocoadays-info.blogspot.jp/2014/05/version-build-number-agvtool.html">Version / Build Number 更新ツール agvtool - Cocoaの日々情報局</a></li>
<li>info.plist を直接いじらずにバージョンをあげたりできる</li>
</ul>
</li>
<li>Build Settings/Versioning をいじって便利に使う
<ul>
<li>Debugの場合はprefixをつけて、<code>dev-1.0</code>としたりできる</li>
</ul>
</li>
<li><script async class="speakerdeck-embed" data-id="af691300be580131ba2f16b66683ddab" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h3>UITableViewCell の highlighted</h3>
<ul>
<li><a href="https://twitter.com/slightair">@slightair</a>さん</li>
<li>UITableViewCellのhighlighted でつまづいた話</li>
<li>UITableViewCellにUIButtonがaddされているようなケース
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 6と<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a> 7 でふるまいが何故か違う</li>
<li>setHighlighted と setSelected のタイミングを調べて対応した</li>
</ul>
</li>
</ul>
<h3>Box C String Tip</h3>
<ul>
<li><a href="https://twitter.com/SCEENEE">@SCEENEE</a>さん</li>
<li><a href="http://qiita.com/SCENEE/items/239f42064b275ad429c4">前回のpotatotips</a>で少し触れたBox C Stringの話</li>
<li>replacement stringの中身を見るのにも使える</li>
<li>Box C Stringを使わずとも書けるが、よりコンパクトにかけて良い</li>
<li>余談としてメソッド名の部分をマクロで書くことができる
<ul>
<li>例. <code>#define ACTION @"action1" - (void)ACTION:(id)sender;</code></li>
</ul>
</li>
<li><script async class="speakerdeck-embed" data-id="42a8f480be6401313e6a7a86bf9f6a20" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script></li>
</ul>
<h1>まとめ</h1>
<p>毎回おもしろいtipsが発表されますが、今回は特に明日から使えるような内容が多かったように感じられました。 ポイントを抑えて日々のコーディングに活かしたいですね。</p>
<p>potatotipsは毎月2週目の水曜をベースに開催されているようです。
応募は1~2週間前にオープンされるようなので、参加されたい方はチェックしてみてください!</p>
<p>発表者のみなさん、<a class="keyword" href="http://d.hatena.ne.jp/keyword/DeNA">DeNA</a>のみなさん、本日はありがとうございました!</p>
<h1>関連記事</h1>
<ul>
<li>過去に開催されたポテチのまとめ記事はこちらです
<ul>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips1">クックパッドのLT会に参加してきたのでiOSのtipsをまとめる</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips2">第2回 #potatotips に参加してきたのでiOSのtipsをまとめる</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips3">第3回はヤフー開催! #potatotips で発表されたiOSのtipsまとめ</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips4">第4回 #potatotips で発表されたiOSに関する9つのtips</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips5">第5回 #potatotips で発表された12個のiOSのtipsをまとめる</a></li>
<li><a href="http://himaratsu.hatenablog.com/entry/potatotips6">第6回はUIEvolution開催! #potatotips で発表されたiOSのtipsまとめ</a></li>
</ul>
</li>
</ul>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/himaratsu/20131113/20131113234202.jpg" alt="f:id:himaratsu:20131113234202j:plain" title="f:id:himaratsu:20131113234202j:plain" class="hatena-fotolife" itemprop="image"></span></p>
himaratsu