試行錯誤ダイアリー

新卒エンジニアが日々の技術的な学び,働き方,日々感じたこと等を書きます

【swift4】センサー値取得するiOSアプリ作ってみた

作ってみたいアプリができたので,iOSアプリの作り方を勉強. とりあえず各種センサーの値を取得して表示するアプリを作成してみた.

センサー値の取得が知りたいという方は 目次の”センサー値を取得してみる”から

環境構築

iOSアプリを作成するためにはXcodeをインストールする. Xcode - Apple Developer こちらからダウンロードしてインストール.
2018年6月4日現在ではHighSierra以上のOSが必要.Sierra以前のOSを使っている人はアップグレード.

Xcodeを起動する

Xcodeを起動すると以下のような画面が出てきます.

f:id:appli-in:20180604010057p:plain:w600
Xcode起動時のウィンドウ

  • Get started with a playground
    playgroundはプログラムの動作確認するための環境.Pythonとかの対話モードみたいな感じですね.
  • Create a new Xcode project
    Xcodeのプロジェクトを作成.アプリを作成するときはこれを選択. 
  • Clone an existing project
    Githubとかにあるプロジェクトをクローンするときはこれ

Create a new Xcode project を選択.

そうしたらこんなウィンドウがでてくる. 項目はそれぞれ以下の表の通りで.適当な値を入力. f:id:appli-in:20180608192417p:plain:w600

項目 意味
Product Name プロジェクト名
Team 開発アカウント名(今回は入力なし)
Organization Name 開発する組織(今回は自分の名前を入力)
Organization Identifire 組織の識別子
Language 言語(今回はSwiftを選択)
Use Core Data データベースの使用の有無
Include Unit Test 単体テストを利用するか
Include UI Test UIテストを利用するか

実装

部品を配置

Nextを押すと開発ウィンドウがでてくる. すでにそれっぽい.

f:id:appli-in:20180608194312p:plain:w600

試しに,テキストフィールドを追加してみる. 下図の赤枠部分を選択し"Label"をドラッグしiPhoneの画面っぽいところにドロップする.

f:id:appli-in:20180608195007p:plain:w600

そうすると,テキストボックスが追加された(TEXTの文字は自分で入力した).ボックスをダブルクリックすると入力モードに切り替わる.

f:id:appli-in:20180608195328p:plain:w300

すごい...

今までGUIアプリって”Labelオブジェクト生成して,〇〇レイアウトで...”みたいな感じで面倒だし,よくわからんけどレイアウトが思い通りにいかないことが多いイメージだったけど,これはめっちゃ簡単だ.位置もドラッグして動かせる.

とりあえず完成形のイメージでレイアウトで実装してみる. 下の"センサー値取得”のボタンを押したら,光センサーの値と加速度センサーの値をその都度表示させる.

f:id:appli-in:20180608202613p:plain:w300

表示させてみる

ウィンドウ画面右上の赤枠のボタンをクリック. f:id:appli-in:20180608203358p:plain

するとエディタがでてくる.

先程作ったラベルをcontrolキーを押しながらエディタにドラッグしようとすると青い線が出る. その線の先をoverride func viewDidLoad()の上に持ってきてドロップする. するとダイアログが出てきて,Nameのところにラベルやボタンの名前を入力する(これはプログラム内で使われる名前). これを残りのラベルとボタンでも同じことをするとこんな感じになる.宣言を勝手にやってくれる.まじかよ.

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var Get: UIButton!
    @IBOutlet weak var Light: UILabel!
    @IBOutlet weak var Acceleration: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

このコード内のoverride func viewDidLoad()は画面をロードするときに呼び出される処理なので, その中にLabelのテキストを記述して,開発ウィンドウ左上の図赤枠部をクリックして実行 f:id:appli-in:20180608204436p:plain:w600

    //毎回画面をロードするときに呼ばれる関数
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        Light.text = "Light : " //Label に "Light :" が表示される
        Acceleration.text = "Acceleration : "//Label に "Acceleration : " が表示される
    }

するとシュミレータが起動してiPhoneの画面が出てくる.シュミレータ上の"Sensor"アプリをタップ.

f:id:appli-in:20180608204653p:plain:w200f:id:appli-in:20180608204822p:plain:w200
シュミレータ起動画面と起動後の画面

表示された.

すごい......

ここまでのあまりの簡単さに感動.

センサー値を取得してみる

輝度センサーの取得
let brightness = UIScreen.mainScreen().brightness

0.0 ~ 1.0 の値が返ります.簡単だ...

これは,画面の明るさの数値で,画面の明るさの設定を変えると変化します.

加速度センサーの取得

こちらはちょっと大変.まずは ”CoreMotion.framework” を追加する. やり方は,画面左部のプロジェクト(今回はSensor),下の図の赤枠部分を選択.

f:id:appli-in:20180609031851p:plain

すると,中心に下図のような画面がでるので,赤枠の "Build Phasese" をクリックする.

"Link Binary With Libraries" の中で "CoreMotion.framework" を追加する.(+マークを押せばダイアログが開いて追加できる) f:id:appli-in:20180609032244p:plain:w600

これでCoreMotionを使えるので,CoreMotionをインポートできる.

import CoreMotion //CoreMotionをインポート

インスタンス生成の生成は

let manager = CMMotionManager() //CoreMotionManagerのインスタンス生成

アップデートするまでの処理は以下の通り.

        manager.accelerometerUpdateInterval = 1 / 2; // アップデート間隔:2Hz
        
        let accelerometerHandler: CMAccelerometerHandler = {
            [weak self] data, error in
            
            self?.Acceleration.text = "Accel(x) : \(data!.acceleration.x)" //Label に "Acceleration : x軸" が表示される xをyやzに変えれば同様に取得できる.
        }
        
        manager.startAccelerometerUpdates (to: OperationQueue.current!, withHandler:accelerometerHandler)

最後に加速度センサーを止めるために,viewDidDisappear関数内などで取得をストップする.今回はボタンを押したときのみ取得なので,アップロード後にすぐに止めています.

        if manager.isAccelerometerAvailable {
            manager.stopAccelerometerUpdates()
        }
ボタンの設定

ボタンの設定も簡単でラベルのときと同じように,ボタンをcontrolキーを押しながらエディタの上に持っていくと青い線が出てきて,適切な場所でドロップすると,下のような画面が出てきて,ConectionをActionにするとドラッグした場所に関数が作成されます.その関数はそのボタンを押したときに実行される関数です. f:id:appli-in:20180611011245p:plain

コード

今回の実装のために書いたコードは以下の通り.今回は加速度はx軸のみ表示させています.ボタンを押したときの加速度を表示させたかったので,アップデート間隔を2Hzにして,ボタンを押したときのみ実行される関数内でアップデートの処理を止めています.(あんまりスマートな書き方ではないと思うので,もし知っている方が入れば教えてください)

import UIKit
import CoreMotion //CoreMotionをインポート

class ViewController: UIViewController {

    @IBOutlet weak var Get: UIButton!
    @IBOutlet weak var Light: UILabel!
    @IBOutlet weak var Acceleration: UILabel!
    
    let manager = CMMotionManager() //CoreMotionManagerのインスタンス生成
    
    //毎回画面をロードするときに呼ばれる関数
    override func viewDidLoad() {
        super.viewDidLoad()
        Light.text = "Light : "
        Acceleration.text = "Accel : "
    }
    
    //ボタンを押したときに実行される関数
    @IBAction func getSensor(_ sender: Any) {
        
        //光センサー値取得
        let brightness = UIScreen.main.brightness //value : 0.0 ~ 1.0
        Light.text = "Light : \(brightness)"  //Label に "Light : 数値"
        
        manager.accelerometerUpdateInterval = 1 / 2; // アップデート間隔:2Hz
        
        let accelerometerHandler: CMAccelerometerHandler = {
            [weak self] data, error in
            
            self?.Acceleration.text = "Accel(x) : \(data!.acceleration.x)" //Label に "Acceleration : x軸" が表示される
        }
        
        //アップデートスタート
        manager.startAccelerometerUpdates (to: OperationQueue.current!, withHandler:accelerometerHandler)

        sleep(1)
        
        if manager.isAccelerometerAvailable {
            //アップデートストップ
            manager.stopAccelerometerUpdates()
        }
    }
    
    //画面を消したときに実行される関数
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

実機でテスト

プログラムがかけたので実機でテストします.

この部分はかなりエラーが出やすいので予め設定をします.

XcodeのPeferencesから"Accounts"タブを開いて,自分のAppleIDを登録してください.

次に,Project Navigatorからプロジェクト(下図左上の赤枠)を選択して,Build Settingsを選択.Product Bundle Identifier jp.他と被らない文字列(自分のメールアドレスなど).プロジェクト名にするとエラーが起きにくいです.SampleとかTestとかだと被りやすいので注意.

”Signing”の設定で”Code Signing Identify”を"iOS Developer"に”Developer Team”を先程登録したAppleIDのアカウントにしてください.

f:id:appli-in:20180611014210p:plain:w600

次に,iPhoneをUSBでPCに接続します.このときに,PCを信頼するか聞かれるので信頼してください.そうしたら下図のように画面上部に端末名が表示されることを確認します(図では黒線が引かれています).

f:id:appli-in:20180611013331p:plain

そして実行(再生ボタンみたいなの)を実行.

するとビルドされて端末にインストールされます.端末にインストールされたアプリを開こうとすると,"信頼されていないエンタープライズ開発元"という表示がでてアプリを実行できません.iPhoneの設定から設定→一般→プロファイルとデバイス管理で自分の開発用アカウントを選択アプリを承認するとアプリを実行可能になります.

実際にアプリを起動して実行したらこんな感じ

f:id:appli-in:20180611015920p:plain:w300

まとめ

iOSアプリ作るのってもっと大変だと思ってたけど,想像していたよりも簡単だった.ビジュアルプログラミングみたいな感じで,レイアウトとかボタンの設定とかが直感的に操作できるのは本当に感動した.簡単なアプリだったら手軽に作れるんだろうなと思った.

これだけは簡単じゃなかったんだけど,実機テストの部分で結構エラーが出て大変だったのでもしエラー出て困ってる人がいたらコメントしてくれたら対応できるかもです.(後日対応記事を書きたいと思っている).