SwiftでFlickrの人気写真を見るアプリを100行で作ったよ
Swiftのビッグウェーブに乗って自分も何かアプリを一つ作ってみようと思い、FlickrのAPIを叩いて人気写真一覧を表示するアプリを作ってみました。 この記事は @himara2 さんの記事「SwiftでTiqav APIを叩くビューワアプリを100行でつくったよ」に触発されて書いたものです。TableViewのサンプルは見かけたので、このアプリではCollectionViewで実装したのと、通信をする際に今までのObjective-Cで多くの人が使っているAFNetworkingを使ってみたのでそこらへんが参考になれば幸いです。ソースコードはgithubにあげたので、おかしなところがあればこちらにpull requestください。
アプリの仕様
- アプリを起動するとFlickr人気写真一覧を取得するAPIにリクエスト
- グリッドビューで取得した写真を表示
- 上のナビゲーションバーのセグメントをタップするとレイアウトを切り替え
- 写真をタップすると写真詳細Viewへ画面遷移
Movie
Screenshot
実装の要点
- Flickr APIへGETリクエスト
- AFHTTPRequestOperationManagerのGET()メソッドを使う
- 写真をグリッド表示
- UICollectionViewを使う
- 画像の非同期読み込み処理
- AFNetworkingのUIImageView拡張(UIImageView+AFNetworking)を使う
ソースコード
Githubにあげました。Xcode6でビルドできます。落としたあと、pod install
してから開いてください。
実装は主にこのファイル( ViewController.swift )にあります。
// ViewController.swift import UIKit // レイアウトタイプをenumで定義 enum LayoutType: Int { case Grid = 0 case List = 1 } class ViewController: UICollectionViewController { var photos:Dictionary[] = [] var layoutType = LayoutType.Grid override func viewDidLoad() { super.viewDidLoad() getFlickrPhotos() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } // Flickr APIにリクエスト func getFlickrPhotos() { let manager :AFHTTPRequestOperationManager = AFHTTPRequestOperationManager() let url :String = "https://api.flickr.com/services/rest/" let parameters :Dictionary = [ "method" : "flickr.interestingness.getList", "api_key" : "86997f23273f5a518b027e2c8c019b0f", "per_page" : "300", "format" : "json", "nojsoncallback" : "1", "extras" : "url_q,url_z", ] SVProgressHUD.show() manager.GET(url, parameters: parameters, success: requestSuccess, failure: requestFailure) } func requestSuccess (operation :AFHTTPRequestOperation!, responseObject :AnyObject!) -> Void { SVProgressHUD.dismiss() self.photos = responseObject.objectForKey("photos").objectForKey("photo") as Array self.collectionView.reloadData() NSLog("requestSuccess \(responseObject)") } func requestFailure (operation :AFHTTPRequestOperation!, error :NSError!) -> Void { SVProgressHUD.dismiss() NSLog("requestFailure: \(error)") } // CollectionView関連のメソッド override func collectionView(collectionView: UICollectionView!, numberOfItemsInSection section: Int) -> Int { return self.photos.count; } override func collectionView(collectionView: UICollectionView!, cellForItemAtIndexPath indexPath: NSIndexPath!) -> UICollectionViewCell! { var photoCell: PhotoCell = self.collectionView.dequeueReusableCellWithReuseIdentifier("PhotoCell", forIndexPath: indexPath) as PhotoCell var photoInfo = photos[indexPath.item] as Dictionary var photoUrl = (self.layoutType == LayoutType.Grid) ? photoInfo["url_q"] : photoInfo["url_z"] // UIImageView+AFNetworkingの画像を非同期で読んでくれるメソッドを実行 photoCell.photoImageView.setImageWithURL(NSURL.URLWithString(photoUrl)) photoCell.photoInfo = photoInfo return photoCell; } func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize { var itemSize :CGSize = (self.layoutType == LayoutType.Grid) ? CGSizeMake(80, 80) : CGSizeMake(320, 150) return itemSize } // SegmentedControlの値が変わった時に呼ばれるメソッド @IBAction func segmentedControlDidChanged(control : UISegmentedControl) { switch control.selectedSegmentIndex { case 0: self.layoutType = LayoutType.Grid case 1: self.layoutType = LayoutType.List default: self.layoutType = LayoutType.Grid } self.collectionView.reloadData() } // 画面遷移時にデータを受け渡すための実装 override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) { if segue.identifier == "ShowPhoto" { var photoCell : PhotoCell = sender as PhotoCell var photoViewController = segue.destinationViewController as PhotoViewController photoViewController.photoInfo = photoCell.photoInfo } } }
やってみての気付き
- CocoaPodsが問題なく使える
- Objective-Cで書かれた既存のライブラリが問題なく(簡単に)使える
- 少なくとも今回使ったAFNetworkingやSVProgressHUDは問題なく使えた
- Objective-Cのライブラリを使う手順は下↓に書きます
- 探してないけど
#pragma mark -
に相当するものはなくなったのだろうか。寂しい - 今までクラスを作る度に生成されていた .h .m と2つのファイルが .swift の一つのファイルにまとまりスッキリする
- コード自体もより簡潔になってスッキリする
- 慣れないところは前のObjective-Cのほうがいいなと思ってしまうけど、Swiftに慣れたらすぐ忘れそう
- たまにObjective-Cとの違いに戸惑う
- initメソッドを実装していないと怒られるとか、Dictionaryに型指定が必要とか
Objective-Cで書かれた既存のライブラリを使う方法
このApple公式ドキュメント「Swift and Objective-C in the Same Project」に書かれている。要は「ProjectName-Bridging-Header.h」ファイルを作って、そこに使いたいObjective-Cのヘッダーファイルをインポートすればよい。
- Objective-C Fileを新規で一つ作る
- すると公式ドキュメントにあるようにダイアログで聞かれるので「YES」を選択する
- ProjectName-Bridging-Header.h ファイルが作られる
- ここに既存のライブラリのヘッダーファイルをインポートするコードを書いていく → こんな感じ
- Swift側で読み込んだObjective-Cのライブラリが使えるようになっている
感想
Swiftを使ってみる前は、今までのUIKitとかの資産はどうなるんだろう、ちゃんと使えるのかな、という疑問があったのですが、UIKitの資産は既に問題なく使えるようになっていました。それだけでなく、既存のOSSなどのObjective-Cソースも上記の方法で簡単に使えることが分かりました。「ProjectName-Bridging-Header.h」を作ってそこでファイルをインポートするだけで、今まで [SVProgressHUD show];
とか書いていたのが SVProgressHUD.show()
として使えるようになります。SwiftとObjective-Cの共存もできますし、移行は想像以上にスムーズにできそうだと感じました。発表されたばかりで、大きな問題なくもうiPhoneアプリが作れてしまう状態になっているのに驚きです。それよりも、今作ってもまだアプリのリリースができないことと、現在はXcode自体が落ちたりエラーをはかずによく分からないところでアプリが落ちたりするので、もうちょっと安定してからがっつり取り組んだほうが効率がよいかもしれません。
参考
以下の記事を参考にさせていただきました。ありがとうございます。
- SwiftのRSS Readerを100行で作ったよ
- SwiftでTiqav APIを叩くビューワアプリを100行でつくったよ
- 今 Swift や iOS 8 について書くのは NDA 違反か調べてみた
- https://www.facebook.com/groups/ios.dev.jp/permalink/741904485830935/
- Swift Cheat Sheet and Quick Reference
- [iOS] 新言語SwiftがObjective-Cよりも良いところ
- Swift and Objective-C in the Same Project
- The Swift Programming Language
UIScrollView(UITableView, UICollectionView)の上にUIGestureRecognizerをおくと、元のUIScrollViewのgestureが効かなくなってしまう問題
- scrollViewを置いてあるUIViewControllerにUIGestureRecognizerDeleageを追加
- gestureRecognizerのdelegateにselfを代入
- 以下メソッドを実装
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; }
「Appleが未だ実現できていない機能を先に作れ」対決形式で行われたiOS勉強に行ってきました #yxcm
2014.2.25 ヤフーで開催されたiOSの勉強会『ヤフー vs クラスメソッド「iOS 炎の7番勝負」』を聞きにいってきました。その感想ポエム日記です。
http://connpass.com/event/5159/
どの発表も面白くて為になりました。行ってよかったです。まだ内定者とは思えないようなしゃべりが達者で知識が豊富な内定者達や、この日のために作ったクラスメソッドさんの投票システムなど見所がたくさんありましたが、個人的に特に印象に残ったのが、最後のヤフーの大将issayさんの発表でした。issayさんは開発イベントで最優秀賞などすごい賞をいつも受賞しておられるアイデアマンで、その発想がどこからいつも生まれてくるのかとても知りたいと思っていました。今回の発表ではその秘訣の一部を教えてもらえたような気がします。
開発者ならば誰しも今までにないアプリを作りたいと思うものですが、その一つの道としてPaul Grahamの「普通のやつらの上を行け」という言葉を引き合いにだして、
Appleが未だ実現できていない機能を先に作れ
とおっしゃっていました。Appleが実装したAPIをそのまま使ったアイデアはもう誰かが考えている!なので、Appleが提供していない機能を考え、それを独自に開発し、それを使ったアプリが世界初のアプリを作る道であると。これには目から鱗が落ちました。今までの自分は既にある機能を使うことばかり考え、こういう発想をしたことがなかったです。今後、アプリなどを考えて行く際にぜひ使っていきたいと思います。
issayさんは実際にこの考え方を実践したデモを披露してくれました。そこではAppleのCore Imageが提供していない視線のトラッキングや、頭のy軸・z軸方向の回転の検出を独自開発し、それを使って顔の表情・視線でアプリを操作するというもの。これだけでも非常に面白いデモでした。また、会場からでた「表情認識以外に注目している技術は何か?」との質問には「カメラは汎用的なセンサで色々な事ができる可能性があるので注目している」とのお答えでした。なるほど。一流のアイデアマンの発想法が少しでも知れた気がしてとても為になったLTでした。
issayさんのスライドとデモ動画