2016/5/25 #potatotips #29 (iOS/Android開発Tips共有会) に参加してきたよ
昨日は赤坂にて開催された potatotips #29 (iOS/Android開発Tips共有会) に参加してきました。主催は bitFlyer さんです。
会場は水槽や植物などもあるオシャレなスペースでした。
いつものようにツイートもまとめておきました。
2016/5/25 #potatotips (iOS/Android開発Tips共有会) 第29回 - Togetter
以下はiOSに関する発表のメモになります。間違いなどあれば教えて下さい。
- WWDC初参加の方に送る 6つのおすすめな巡り方
- Bitriseを使っています
- Segue をもっと使いやすくするTips
- AppStoreで最新バージョン以外のアプリをダウンロードする話
- Introducing Anglerfish
- Swift Package Manager (SwiftPM, SPM)
- スタイルの一貫性を保つ
- 所感
WWDC初参加の方に送る 6つのおすすめな巡り方
mogmet さんによる発表です。WWDCに初めて参加する人向けに、おすすめの現地の巡り方を紹介されていました。
mogmet さんによると、WWDCの各セッションは1Fで視聴したほうがリアルタイムに英語の字幕を見ることができるため、セッションも聞き取りやすくなるそうです。これは参加した人にしかわからない情報なのでとても嬉しい情報ですね。他にもたくさんのTIPSを共有されていました!
- キーノート前日の朝までには到着しよう!
- キーノートに参加しよう!
- セッションは1Fで視聴しよう!
- ラボに張り付きましょう!
- 夜はパーティにでかけよう!
- 帰国後WWDC勉強会に出る
Bitriseを使っています
kurikazu さんによる発表。私も愛用している Bitrise についてのお話でした。
Bitrise は iOS, Android, Xamarin に対応したCIサービスです。無料枠もあります。GUIベースで「ワークフロー」と呼ばれる一連のステップ(git clone, pod install, Unit Test など)を追加していくのが特徴です。Slackなど色々なサービスにも対応しているそうです。
Apple の TestFlight にも対応していますが、Submit for Testflight
オプションには罠があり、yes
にするといきなりアップルにアプリがアップロードされるので注意が必要とのこと。
Segue をもっと使いやすくするTips
hirose_yudai さんによる発表です。Segueに関するお話でした。
Segueを使いやすくしてくれるライブラリとして ResourceKit というライブラリがあります。
これを使うことにより
- 補完が効く
- typoを防ぐことができる
- Replaceし忘れがなくなる
などのメリットがありますが、さらに便利な SegueAddition というライブラリがあります。
これによって
- 値渡しが楽になる
- より狭いスコープで完結する
- 循環参照しない
などのメリットが得られます。
さらに、ResourceKit と SegueAddition を併用することで更に便利になるそうです。詳しくはスライドをご覧ください。
AppStoreで最新バージョン以外のアプリをダウンロードする話
hikarusato さんによる発表です。AppStore からアプリをダウンロードする際のリクエストを書き換えて、過去のバージョンをダウンロードするという素晴らしいTipsでした!
あるとき、旧バージョンをビルドしようとしたら、古いXcodeと互換性がないためビルドできない!ということがあったそうです(開発者あるある)。そこで、AppStore から過去のバージョンをダウンロードしようと思ったのがきっかけなんだそうです。
用意するものは次の3つ:
AppStore には初回リリースからすべてのバージョンが保存されている(おそらく)ことも知らなかったので、非常に勉強になりました!
Introducing Anglerfish
dealforest さんによる発表。私も愛用している Xcode プラグイン Anglerfish の紹介でした。
GitHub - dealforest/Anglerfish: sort the recently used simulators
iOS シミュレータが増えてくると、プルダウンから選択するときにわけが分からなくなりますよね。それを解決してくれるのが Anglerfish です!シミュレータを使った順にソートしてくれます。
ちなみに Anglerfish という名前は「アンコウ」からきているそうです。
@dealforest 狙ったものをピックアップする感覚で アンコウ Anglerfish (Anglerは"釣り")https://t.co/meLe3Vh4X2
— にわタコ (@niwatako) 2016年5月18日
Swift Package Manager (SwiftPM, SPM)
神戸から参加された JPMartha さんの発表!Swift Package Manager のお話でした。
Swift Package Manager は CocoaPods や Carthage のように、ライブラリを管理するためのツールです。Apple純正の管理ツールであり、将来的にはXcodeに組み込まれるそうです。今回は Swift Package Manager の入門的な話と、Swift Package Managerを駆使したツールの話が中心でした。
懇親会でも色々と質問させて頂きました。Twitterで補足をいただき、ありがとうございます 🙇🏻
@koogawa 補足しますとここに書かれていることをふまえてお話しました。
— JPMartha (@JPMartha_jp) 2016年5月25日
・Swift 3.0 は Swift Package Manager を含む
・Swift 3.0 は将来の Xcode に搭載される
などhttps://t.co/tP27MQIp0T
ちなみに、JPMartha さんはニューヨークで開催されている Brooklyn swift developers に登壇されるそうです!
スタイルの一貫性を保つ
今回の主催である bitFlyer の hayashi331 さんによる発表です。
人間が行動するときにかかる負荷は「運動」「視覚」「認知」の3つだと言われているそうです。そして、運動よりも視覚よりも重い認知負荷を下げるのがもっとも重要なんだそうです。そのためにも「スタイルの一貫性を保つこと」が大事であり、今回は bitFlyer で作成している
- NSAttributedString + Builder
- UICatalog
について紹介されていました。
所感
今回は質疑応答ありのスタイル*1でしたが、時間通りに進んでいてタイムキーピングが素晴らしいと思いました。
ちなみに、bitFlyer さんは iOS エンジニアを大募集されているそうです!
よろしくお願いいたしますhttps://t.co/fcCU1tilKt#potatotips
— yomoapp(本人) (@yomoapp) 2016年5月25日
RxSwiftを使ってfoursquareのベニューを取得するメモ
2016.10.23 追記:Swift 3.0 対応版を作成しました
RxSwift のメリットを理解するには実際に使ってみるのが一番!ということで、とりあえず foursquare のベニューを取得するサンプルを作ってみました。
※RxSwift は絶賛勉強中なので間違ったことを書いている可能性が高いです。ツッコミ歓迎です!
動作環境
- Swift 2.2
- RxCocoa (2.4)
- RxSwift (2.4)
- SwiftyJSON (2.3.2)
- Xcode 7
APIクライアント
APIにアクセスする部分を作ります。戻り値を Observable<[Venue]>
にしているのがポイントです。
func send() -> Observable<[Venue]> { return Observable.create{ (observer) in let client = FoursquareAPIClient(accessToken: "YOUR_TOKEN") let parameter: [String: String] = [ "ll": "40.7,-74", ]; client.requestWithPath("venues/search", parameter: parameter) { [weak self] (data, error) in let json = JSON(data: data!) let venues = (self?.parseVenues(json["response"]["venues"])) ?? [Venue]() observer.on(.Next(venues)) observer.on(.Completed) } return AnonymousDisposable {} } } func parseVenues(venuesJSON: JSON) -> [Venue] { var venues = [Venue]() for (key: _, venueJSON: JSON) in venuesJSON { venues.append(Venue(json: JSON)) } return venues }
通信ライブラリは拙作 FoursquareAPIClient を使用しました。
ViewModel
ViewModel から先ほどの send
を呼び出す部分です。
public func fetch() { self.send() .subscribe { [weak self] (event) -> Void in switch event { case .Next(let value): self?.venues.value = value case .Error(_): () case .Completed: () } } .addDisposableTo(disposeBag) }
戻り値が Observable<[Venue]>
なので、これを subscribe して、返ってくる値(ベニューリストなど)を処理しています。
ViewController
ViewController は30行程と、かなりスッキリしました。rx_itemsWithDataSource
でベニューリストとTableViewをBindしているのがポイントです。ViewModel のベニューリストに変化があるとTableViewがリロードされます。
import UIKit import RxSwift import RxCocoa class ViewController: UIViewController { @IBOutlet weak var tableView: UITableView! var viewModel = ViewModel() var dataSource = DataSource() var delegate = Delegate() let disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() self.tableView.delegate = self.delegate self.viewModel.fetch() self.viewModel.venues .asDriver() .drive ( self.tableView.rx_itemsWithDataSource(self.dataSource) ) .addDisposableTo(self.disposeBag) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
完全なソースコードはこちらです。
GitHub - koogawa/RxSwiftSample: RxSwiftSample
参考にさせて頂いた記事など
地図から位置情報を選択できる「LocationPickerController」を公開しました
地図から位置情報を選択する処理を毎回書くのが面倒くさいので、ライブラリとして公開しました。
位置情報は CLLocationCoordinate2D
で取得できます。
使い方
- プロジェクトに
CoreLocation.framework
とMapKit.framework
をリンクします - 位置情報を使う目的を info.plist の
NSLocationWhenInUseUsageDescription
に記載します CoreLocation
とLocationPickerController
をインポートしますLocationPickerController
を初期化しますLocationPickerController
を表示すると地図を表示します- Doneをタップすると位置情報がクロージャで取得できます
import CoreLocation import LocationPickerController
let viewController = LocationPickerController(success: { [weak self] (coordinate: CLLocationCoordinate2D) -> Void in self?.locationLabel.text = "".stringByAppendingFormat("%.4f, %.4f", coordinate.latitude, coordinate.longitude) }, failure: nil) let navigationController = UINavigationController(rootViewController: viewController) self.presentViewController(navigationController, animated: true, completion: nil)
インストール方法
LocationPickerController
は CocoaPods に対応しています。Podfile
に下記一行を追加して pod install
してください。
pod "LocationPickerController"
動作環境
iOS 8.0 以上で動作します。
プルリク歓迎です!
まだまだ Swift 勉強中であり、なかなか Swifty な書き方ではないことを自覚しております。もっと Swift らしい書き方ができるよ!という方はぜひプルリクエストをお送りください🙇🏻
すでに [twitter:@yimajo] 様より Swiftyなプルリク を頂きました!ありがとうございます。
iOSで検知できるセンサー12項目をまとめた「iSensor」のSwift版を公開しました
輝度センサーやモーションセンサーなど、iOSで検知できる様々な項目をまとめたサンプル集 iSensorSwift をGithubで公開しました。
▼機能の1つである「輝度センサー」のスクリーン
iSensorSwift は昔書いたこちらのサンプル集を Swift で書き直したものになります。
興味のある方は、ぜひ使ってみてください!😀
検知できる項目
- 光・音声系
- 輝度センサー
- 近接センサー
- シェイクジェスチャー
- マイクの音
- 位置情報系
- 緯度・経度
- 電子コンパス
- 標高
- 移動・動作系
- 加速度センサー
- 歩数・進行状況
- 移動速度
- その他
- 顔検出
- バッテリー残量
実装方法を解説した記事
- 【Tips】iOSで輝度センサーを使う(Swift対応) - koogawa blog
- 【Tips】iOSで近接センサーを使う(Swift対応) - koogawa blog
- 【Tips】iOSでシェイクジェスチャーを検知する(Swift対応) - koogawa blog
- 【Tips】iOSで加速度センサーを使用する - CoreMotion(Swift対応) - koogawa blog
- 【Tips】iOSデバイスのバッテリー残量を取得する(Swift対応) - koogawa blog
- 【Tips】iOSで位置情報を取得する方法(Swift 3.0対応) - koogawa blog
- 【Tips】iOSで標高を取得する方法(Swift 3.0対応) - koogawa blog
- 【Tips】iOSで電子コンパスを使う(Swift編) - koogawa blog
- 【Tips】iOSでマイクの音を検知する(Swift編) - koogawa blog
- 【Tips】iOSで歩数をカウントする(Swift編) - koogawa blog
- 【Tips】iOSの顔検出機能を使ってみる(Swift編) - koogawa blog
【Tips】iOSの顔検出機能を使ってみる(Swift編)
数年前に書いた下記記事が古くなってきたので、Swift編 として書き直しました。
【Tips】iOSの顔検出機能を使ってみる - koogawa blog
iOS 5から追加された CIDetector
を使って、顔検出機能を使う方法をメモしておきます。
実装方法
まずは「CoreImage.framework」を追加します。
インスタンスを生成します。
let detector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
ofType
には検出種類を指定します。今回は顔検出なので、CIDetectorTypeFace
を指定します。
options
には検出精度 CIDetectorAccuracy
等を指定できます。
- CIDetectorAccuracyLow - 精度は低いが、パフォーマンスは良い
- CIDetectorAccuracyHigh - 精度は高いが、パフォーマンスは悪い
次に、顔検出を実行します。
// UIImage から CGImage を作る let cgImage = image.CGImage // CGImage から CIImage を作る let ciImage = CIImage(CGImage: cgImage) // 顔検出実行 let features = detector.featuresInImage(ciImage, options: [CIDetectorSmile : true])
featuresInImage
の引数には、顔検出したい画像を CIImage
クラスで指定します。
今回は検出された顔が笑っているかどうかも検出したいので options
に CIDetectorSmile
をセットしました。
正常に顔が検出されると、検出結果が CIFaceFeature
オブジェクトとして返ってきます。このオブジェクトには、検出された顔の範囲や、目と口の位置などが含まれます。
- bounds - 顔の範囲
- hasLeftEyePosition - 左目の位置を検出できたか
- hasMouthPosition - 口の位置を検出できたか
- hasRightEyePosition - 右目の位置を検出できたか
- leftEyePosition - 左目の位置
- mouthPosition - 口の位置
- rightEyePosition - 右目の位置
- hasSmile - 顔が笑っているか
- leftEyeClosed - 左目が閉じているか
- rightEyeClosed - 右目が閉じているか
ここで注意したいのは、CoreImage
は、左下の座標が (0,0) となる点です。よって、検出元画像の上に部品を載せたい場合は、座標をUIKitの座標系に変換する必要があります。
var transform = CGAffineTransformMakeScale(1, -1); transform = CGAffineTransformTranslate(transform, 0, -self.imageView.bounds.size.height); // UIKit座標系に変換 let faceRect = CGRectApplyAffineTransform(feature.bounds, transform)
これで顔検出ができました。
顔検出というと難しそうなイメージが有りますが、座標系のところ以外は、意外と簡単に使用できますね。
サンプル
補足
- iOS 8からはQRコードや画像の中の四角形も検出できるようになったようです
- iOS 9からは文字検出もできるようになったようです(文字の領域を検出するもので、文字の内容までは認識できない)
- 【iOS 9】Core Image の新機能:文字認識/追加フィルタ47種 - その後のその後
【Tips】iOSで歩数をカウントする(Swift編)
数年前に書いた下記記事が古くなってきたので、Swift編 として書き直しました。
【Tips】iOSで歩数をカウントする - koogawa blog
CoreMotionを使って、歩数カウントを取得する方法をメモしておきます。
動作環境
Xcode 8.0 + Swift 2.2
実装方法
まずは「CoreMotion.framework」を追加します。
ヘッダをインポートします。
import CoreMotion
歩数をカウントする
歩数をカウントするためには CMPedometer
を使います。
iOS 7で登場した CMStepCounter
は iOS 8 で早くも deprecated になりました。早かったですね…
まずはインスタンスを生成します。メンバ変数にしないとうまくいかないので注意です。
let pedometer = CMPedometer()
startPedometerUpdatesFromDate
メソッドで歩数のカウントを開始します。
if CMPedometer.isStepCountingAvailable() { self.pedometer.startPedometerUpdatesFromDate(NSDate(), withHandler: { [weak self] (data: CMPedometerData?, error: NSError?) -> Void in // 歩数が更新されるたびに呼ばれる dispatch_async(dispatch_get_main_queue(), { if data != nil && error == nil { self?.stepLabel.text = "step: \(data!.numberOfSteps)" } }) }) }
- 第1引数:どの時点からのデータを呼び出すか指定(今回は現在日時を指定)
- 第2引数:歩数更新時に呼び出す handler
第2引数で指定する handler には、計測を始めてからの累計歩数、移動距離など様々な情報が返ってきます。詳細はアップルの公式ドキュメントを参照してください。
歩数カウントが不要になったら、忘れずにカウントを停止しておきます。
self.pedometer.stopPedometerUpdates()
アクティビティの変化を取得する
また、歩数以外にもユーザのアクティビティ情報(歩いているのか、走っているか等)も取得できます。
まずはインスタンスを生成します。メンバ変数にしないとうまくいかないので注意です。
let activityManager = CMMotionActivityManager()
取得を開始します。
if CMMotionActivityManager.isActivityAvailable() { self.activityManager.startActivityUpdatesToQueue(NSOperationQueue.mainQueue(), withHandler: { [weak self] (data: CMMotionActivity?) -> Void in dispatch_async(dispatch_get_main_queue(), { // アクティビティが変化するたびに呼ばれる }) }) }
アクティビティは CMMotionActivity
というクラスで返ってきます。このクラスには次のプロパティが含まれます。
型 | プロパティ | 意味 |
---|---|---|
NSDate | startDate | アクションが発生した時間 |
CMMotionActivityConfidence | confidence | データの精度(Low/Medium/High のいずれか) |
BOOL | stationary | 静止状態 |
BOOL | walking | 徒歩中 |
BOOL | running | ランニング中 |
BOOL | automotive | 自動車や電車等の乗り物に乗っている状態 |
BOOL | unknown | 不明なアクティビティ |
どれかひとつの動作が true
になるというわけではなく、例えばautomotive
と stationary
が同時に true
になる状況もありえるようです。
最後は忘れずに停止しておきます。
self.activityManager.stopActivityUpdates()
サンプル
注意点
- 歩数カウント機能を使用するには、「M7」以上のコプロセッサが必要になります
- M7搭載機種:iPhone 5s
- M8搭載機種:iPhone 6, iPhone 6 Plus など
リンク
2016/4/20 #potatotips #28 (iOS/Android開発Tips共有会) に参加してきたよ
昨日は南青山にあるエウレカさんで開催された potatotips #28 (iOS/Android開発Tips共有会) に参加してきました。
とても綺麗なオフィスでした。
いつものようにツイートもまとめておきました。
2016/4/20 #potatotips (iOS/Android開発Tips共有会) 第28回 - Togetter
Androidの発表内容については、すでに id:konifar さんが素晴らしいまとめを公開されています。
以下はiOSに関する発表のメモになります。間違いなどあれば教えて下さい。
- PlaygroundでカスタムUIのプロトタイピング
- Debug Remote / Local Notification on watchOS
- RxSwiftのドライバー
- Swiftにわか勢な自分がMacアプリを作ってRxSwiftを使えるようになった話
- Repository pattern in Swift
- tvOS tips
- 国際カンファレンスに登壇する - 応募編
- iOS Universal Linkについて
- 所感
PlaygroundでカスタムUIのプロトタイピング
milkit さんによる発表。Xcode の Playground についてのお話です。
Playgroundは日々進化しており、なんとたった3行で TableViewController
が表示できてしまう。そして、アニメーションや AutoLayout にも対応している。更に、Xcode 7.3からタップイベントも取れるようになったんだとか。
Debug Remote / Local Notification on watchOS
shingt さんによる発表。watchOS 上で扱う Local Notification のお話です。
watchOS における Remote Notification のテストは、Xcode に仕組みが用意されているため割と簡単。それに対し、Local Notification は仕組みがないのと、引数が UILocalNotification
オブジェクトで渡ってくるので、テストがとても大変。そこで、Remote/Local Notification のラッパーを作ったという素敵なお話でした。
RxSwiftのドライバー
Motoki Narita さんによる発表。RxSwift の Driver についてのお話でした。
アカウント登録画面を例に、入力されたユーザ名がすでに使われているかどうかを Validate するサンプルを使って Driver
の解説をされていました。
- https://github.com/ReactiveX/RxSwift/blob/master/Documentation/Units.md
- RxSwift/Units.md at translates-into-japanese · tid-kijyun/RxSwift · GitHub(和訳)
Swiftにわか勢な自分がMacアプリを作ってRxSwiftを使えるようになった話
y.imajo さんによる発表。Macアプリを作ってRxSwiftを使えるようになった話でした。
発表が始まった途端、スクリーンにハッシュタグ #potatotips のツイートが流れているな〜と思っていたら、実はそれ自体が今回発表するMacアプリだった!という驚きの内容でした。
今回のMacアプリのソースコードはGitHubに公開されているそうです。
手を動かさないとRxSwiftは理解できない
これはその通りだなぁ、と思いました。
Repository pattern in Swift
naoty さんによる発表。リポジトリパターンのお話です。
リポジトリパターンを使うことで、オブジェクトをWebAPI経由で取得するのか?Realmから取得するのか?などを知る必要がなくなり、疎結合なコードを書くことが可能になります。今回は「レシピデータ」をリポジトリを介して取得する処理をSwiftで実装する実践的な内容でした。
tvOS tips
koutalou さんによる発表。tvOSのお話です。最近、マネーフォワードのtvOSアプリを作られたそうです!
個人的には tvOS にも TabBarController と NavigationBar の概念があったことや、WebViewが使いないことを知らなかったので色々と勉強になりました。
国際カンファレンスに登壇する - 応募編
shu223 さんこと堤さんによる発表。堤さんは国際カンファレンスである UIKonf / iOSCon に登壇されるそうです!🎉
発表の中では、応募する理由、参加することのメリット、カンファレンスの探し方など、なかなか聞くことのできない貴重なお話を聞くことができました。
スライドなどは堤さんのブログにまとめられているようです。
iOS Universal Linkについて
最近ボルダリングにハマっているという TachibanaKaoru さんによる発表。iOS 9 から使えるようになった Universal Link のお話でした。
Universal Link の仕組み自体は知っていたのですが、SFSafariViewController, WKWebView, UIWebView の中では無効になる事実や、自分でURLを入力した場合も無効になるというTipsが知れたのは良かったです。
また、Smart App Banner との違いについても触れられていました。Universal Link と Smart App Banner は目的が違うものになるため、別々に実装する必要があるとのことです。
所感
ポテチでもRxの発表が増えてきており、流行ってるんだなぁ〜というのを再認識しました。
また、発表中も程よいボリュームでBGMが流れていて良いな、と思いました。
#potatotips さり気なくかかっているBGMが発表の邪魔するわけでもなく、とてもよい感じ
— Kosuke Ogawa (@koogawa) 2016年4月20日
現場からは以上です。*1
*1:こにふぁーさんをリスペクトしてみました。怒られたら消します