2015-10-31

バックグラウンドの Location update で、local notification を出す iOS アプリ

移動中に、地理的な条件によって、ユーザーに指示をだす iOS アプリを作ろとうしている。

地理的な位置を管理する CoreLocation サービスは、バックグラウンドでも動き続けるので、これを使うことにした。いろいろ情報があったけれど、集約してひとつのアプリとして動かすのに時間がかかったのでメモしておく。


  • XCode Version 7.1 (7B91b) on OS X El Capitan 10.11.1
  • Xcode で File → New → Project → iOS Application → Single View Application
  • CoreLocation framework をプロジェクトに追加
  • Background の "Location updates" を有効にする
  • info.plist に NSLocationAlwaysUsageDescription キーを追加。値はユーザーに許可を求めるときの文字列。
  • この例では ViewController.swift には触らない。けれど、以下のコードを ViewController クラスに実装しても動く。
  • AppDelegate.swift を以下のように編集する

import UIKit
import CoreLocation

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
    var window: UIWindow?
    lazy var locationManager: CLLocationManager! = {
        let manager = CLLocationManager()
        manager.desiredAccuracy = kCLLocationAccuracyBest
        manager.pausesLocationUpdatesAutomatically = false
        manager.allowBackgroundLocationupdates = true
        manager.delegate = self
        manager.requestAlwaysAuthorization()
        return manager
    }()

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        let settings = UIUserNotificationSettings(forTypes: [.Alert], categories: nil)
        UIApplication.sharedApplication().registerUserNotificationSettings(settings)
        locationManager.startUpdatingLocation()
        return true
    }

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let cond = true  // 何か条件判定をいれる。常に true だと通知しまくるので注意。
        if cond == true {
            let notification = UILocalNotification()
            notification.alertBody = "Hello"
            UIApplication.sharedApplication().presentLocalNotificationNow(notification)
        }
    }
    // 他のメソッドはそのまま触らない
}

allowBackgroundLocationupdates を true にすることに気づかなくて長い時間を費やしてしまったデフォルトの false のときアプリが foreground と background のときにはデリゲート関数が呼ばれるけれどsuspend 状態では呼ばれないなので最初は通知が出るがしばらくすると出ないという現象が起こるそのように見えた気がする

ざっとでもいいから、ドキュメントを読む癖をつけねば。

2015-10-24

iOS の UILocalNotification でユーザーに指示を出す

iOS 9.1/Swift で定期的に音とバイブを鳴らすコードを書いた移動中の人間にスマートフォンから音声とバイブで〇〇せよという指示を与えられるかを確認することが目的だ

NSTimer を使って、定期的に関数を呼び出し、その関数の中で AVAudioPlayer オブジェクトの play() メソッドと、AudioServicesPlayAlertSound(SystemSoundID(kSystemSoundID_Vibrate)) を呼び出すコードを書いた。アプリがフォアグラウンドにあるときは、定期的に音もバイブも鳴るのだけれど、バックグラウンドに入ると音もバイブも鳴らない。

iOS アプリの開発経験のある斧さん仮名によると用途次第だが音はともかくバイブを制御できることを期待するなタイマーもだるいから諦めろ」ということだった

今回はあくまで実験なので、UILocalNotification をいくつも作って、スケジューリングすることにする。

さて、ポケットにスマートフォンを入れて、移動してみたところ、バイブが鳴ってることは分かるが、仮に振動パターンを作ったとしても、判別できなさそうだ。

一方、ボリュームを大きくしていると、胸ポケットに入れてても、尻ポケットに入れてても、音声による指示は聞こえる。

// Permission
UIApplication.sharedApplication().registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [.Sound, .Alert], categories: nil))

// Setup local notifications
let COUNT = 5
Let INTERVAL = 60

for i in 0 ..< COUNT {
    let notification = UILocalNotification()
    notification.alertBody = alert
    notification.timeZone = NSTimeZone.defaultTimeZone()
    notification.fireDate = NSDate(timeIntervalSinceNow: Double(i+1) * INTERVAL)
    notification.soundName = "foo.m4a"
    UIApplication.sharedApplication().scheduleLocalNotification(notification)

2015-10-17

iPhone アプリ開発をかじろうとする

iPhone/Android アプリのディレクション仕様策定ともろもろの意思決定みたいなのをしたことはあるのだけれど実際に作ったことはなかっただいたいが通信やドメインモデル的なデータ構造を主に担当することが多かったわけで

そんなわけで iPhone アプリの作り方を知ろうと思い立った。

だいたい2日もすると、やる気がなくなってしまうので、勢いで本を購入。簡単すぎるくらい簡単なところから、と思って、簡単そうな本を買ってやってみた。基本的に書いたとおりに写経すればいいんだけど、うっかり、Xcode 7 をインストールしてしまって、微妙に違う箇所があったりする。



この本、構成はいいんだけど、たとえがイマイチなので、好きではない。例示ではなくて、たとえ。

とはいえ、書いてあるとおりに書くと、動く。その後で解説がある、という構成は、私にとって分かりやすい。

続いて、Apple のサイトにある iOS 9、 Xcode 7 のチュートリアルもやってみた。ふむふむ。

Swift は言語仕様的に、冗長なところがあって、同じことをするために複数の書き方があるように見える。class があれば struct は要らないだろとか、継承、extension、プロトコルが地味に被ってるようなとか、delegate は機能じゃなくてデザインパターンかよとか。

けれど、誰かが「言語の問題ではくて、OS X や iOS アプリの既存フレームワークを使うために、そのようなことになってしまっている」と話している見て、納得した。

アプリ開発を請け負えるかと言われると、まったくもって無理ではあるけれど、デバッグの手伝いくらいは(ピザを注文する以外にも)できるようになったような気はする。



2015-10-10

知人、Facebook 広告、Yahoo! 知恵袋でインタビュー対象を探す

作ろうとしている製品について、知人にインタビューをしてみた。「顧客はこのような問題を持っているであろう」という仮説の検証を目的にしている。

それとは別に、Facebook 広告を出して、アンケートページに誘導する、というのを試した。けれど、アンケートへの回答率が低かったので、数日で終了。検証インタビューを勧めていた本にも「いきなりアンケートがあると、回答率が下がる」と書いてあったのに、見逃していた。

インタビュー対象を探すのが目的だったので、Facebook 広告の対象は日本在住を設定した。日本語版と英語版を用意したところ、それぞれ傾向が違う。日本語では「私の年収低すぎ!」みたいなネガティブな問題定義がある画像で、ダントツでクリック率が高い。また反応するは 30-50代 の男性が90%以上である。

英語版では「年収が上がった!」みたいなポジティブな結果を連想させるメッセージがついた画像に、比較的クリック率が高い。男女比は 6:4 くらい。ただ英語話者というのは非常に広い文化圏に分布するので、セグメントとしては大きすぎるかも知れない。

ふと思い立って Yahoo! 知恵袋で、質問してみた。自分が言いたいことを書く回答者がいるかもなぁという仮説があったけど、どうせタダなので試してみたわけだ。結果、やっぱり、そういう人がいる、とういうことが分かった。仮説の検証。

2015-10-03

リーン顧客開発を試している

シンディ・アルバレスの「リーン顧客開発売れないリスク」を極小化する技術 (THE LEAN SERIES) を読んで実践しはじめたリーン・スタートアップから派生したシリーズの本で原題は「Lean Customer Development: Building Products Your Customers Will Buy」という副題は「顧客が購入する製品を作る」というところか



売れる製品とは、誰かが金を払うだけの価値を見出しているからだ。つまり、その誰かの課題を解決している。

この本は、課題の設定がそもそも妥当なのか? 解決策は妥当なのか? を検証する方法を紹介している。具体的には、想定顧客へのインタビューを通して、仮説を検証するガイドである。

リーン・スタートアップ関連の本を読んで、いつも「製品を作る前に、潜在顧客に話すの?」と懐疑的だった。けれど、軽い気持ちとは言え、いくばくかの時間をかけて作ったちょっとしたオンラインツールに、ぜんぜんアクセスがないという経験をした。2つ連続で。

需要があるのか? そもそも課題設定も妥当なのか? 妥当だとして、どうやって人を引っ張ってくるんだ? という問に、まったく答えられないことを認めざるをえない。この本にも「製品/サービスの機能よりも、流通、価格、協業あたりにリスクがあることが多い」と指摘されている。おぅふ。

そんなわけで、課題の想定が妥当かのインタビューの準備をしている。インタビューの練習くらいの気持ちで、身近な知人と話しただけで、いきなり学びがあって驚いた。来週も、知人にインタビューのお願いをしてある。