iBeaconでクリスマスに備えよう！

お初の方は初めまして、夏休みの宿題は夏休みが終わった後にやる派のyoutenです。
この投稿は2013年のiBeacon Advent Calendarの6日目の記事です。

みなさん、Advent Calendar楽しんでますか？

iBeacon Advent Calendar担当の当日、帰宅したらLightningケーブルを会社に忘れてきたことに気づいたのです。Xcode5のシミュレータではiBeaconは動作しないのです。よって肝心の動作確認をいっさい行えていないのですがなんとかなるでしょう。人生にトラブルはつきものです。

さて、そもそもAdvent Calendarってなんでしたっけ？
そうです、クリスマスを楽しみに待つためのものです。

皆さんクリスマスが待ち遠しいですか？僕は24日に休みを取ろうと考えております。
考えている以上のことはありません。

さて、そんなAdvent Calendarらしさを求めて、iBeaconでクリスマスに備えることにしましょう。

ここで振り返って、iBeaconってなんでしたっけ？

「特定の何かがどんな感じで近づいているか、ゆるふわな感じで分かる」

そう、これがiBeaconです。

「クリスマス」「近づく」「ハッピー！」

このキーワードでもうお分かりですね、クリスマス・イブの夜に俺のことを温かく出迎えてくれる嫁をiBeaconで作りましょう。

小さい方のも悪くないですが、やっぱり大きい方がいいですよね、まずiPadを用意します。女房と畳は新しい方がいいって言いますよね、ちょっとスリムなiPad Airで出だしからパーフェクトです。

続いて絵心の無い俺を手助けしてくれるコミPo!さんに手伝っていただいて、嫁の写真を準備します。

![xmas_001.png](https://qiita-image-store.s3.amazonaws.com/0/11296/a99b6514-f2be-5786-ac03-5dace28dc764.png) ![xmas_002.png](https://qiita-image-store.s3.amazonaws.com/0/11296/003a2727-3885-cde4-0a06-b74c3552e477.png)

![xmas_003.png](https://qiita-image-store.s3.amazonaws.com/0/11296/382b98a0-6ff5-7df1-f020-568ec8f0e742.png) ![xmas_004.png](https://qiita-image-store.s3.amazonaws.com/0/11296/45c11467-a822-ae8e-fa34-13ade7d27f24.png)

もう賢明な皆様には、素晴らしい嫁がどう出迎えてくれるか分かりましたよね。
しかし、ここでさらにiOS7から登場した＋αのエッセンスを加えます。手は抜きません。

```objc
//
//  ViewController.m
//  XmasBeacon
//
//  Created by youten on 2013/12/06.
//  Copyright (c) 2013年 youten. All rights reserved.
//

#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#import <AVFoundation/AVFoundation.h>

@interface ViewController () <CLLocationManagerDelegate>

@property (nonatomic) CLLocationManager *locationManager;
@property (nonatomic) NSUUID *proximityUUID;
@property (nonatomic) CLBeaconRegion *beaconRegion;

@end

@implementation ViewController {
    NSArray *YOME_IMAGE;
    NSArray *YOME_SPEECH;
    AVSpeechSynthesizer *_speechSynthesizer;
    int _yomePhase;
    CLProximity _privProximity;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    YOME_IMAGE = @[@"xmas_001.png", @"xmas_002.png", @"xmas_003.png", @"xmas_004.png"];
    YOME_SPEECH = @[@"あ、帰ってきたかな？",
                   @"おかえりなさい、ごはんにします？おふろにします？",
                   @"それとも、わ・た・し？",
                   @"メリークリスマス、ちゅっ！"];
    
    // iBeacon
    if ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]]) {
        self.locationManager = [CLLocationManager new];
        self.locationManager.delegate = self;
        self.proximityUUID = [[NSUUID alloc] initWithUUIDString:@"E0760C30-457E-48DA-80CA-ECF0B8ECD1FA"];
        self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:self.proximityUUID
                                                               identifier:@"yome"];
        [self.locationManager startMonitoringForRegion:self.beaconRegion];
    }
    
    // AVSpeechSynthesizer
    _speechSynthesizer = [[AVSpeechSynthesizer alloc] init];
    
    // Tap
    UITapGestureRecognizer *yomeTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(yomeTapped:)];
    yomeTap.numberOfTapsRequired = 1;
    _yomeImage.userInteractionEnabled = YES;
    [_yomeImage addGestureRecognizer:yomeTap];
    [self updateYome:0];
}

- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region
{
    [self.locationManager requestStateForRegion:self.beaconRegion];
}

- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
    switch (state) {
        case CLRegionStateInside: // リージョン内にいる
            if ([region isMemberOfClass:[CLBeaconRegion class]] && [CLLocationManager isRangingAvailable]) {
                [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
            }
            break;
        case CLRegionStateOutside:
        case CLRegionStateUnknown:
        default:
            break;
    }
}

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    if ([region isMemberOfClass:[CLBeaconRegion class]] && [CLLocationManager isRangingAvailable]) {
        [self.locationManager startRangingBeaconsInRegion:(CLBeaconRegion *)region];
    }
}

- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    if ([region isMemberOfClass:[CLBeaconRegion class]] && [CLLocationManager isRangingAvailable]) {
        [self.locationManager stopRangingBeaconsInRegion:(CLBeaconRegion *)region];
    }
}

- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
{
    if (beacons.count > 0) {
        CLBeacon *nearestBeacon = beacons.firstObject;
        if (_privProximity != nearestBeacon.proximity) {
            switch (nearestBeacon.proximity) {
                case CLProximityImmediate:
                    [self updateYome:3];
                    break;
                case CLProximityNear:
                    [self updateYome:2];
                    break;
                case CLProximityFar:
                    [self updateYome:1];
                    break;
                default: // unknown
                    [self updateYome:0];
                    break;
            }
        _privProximity = nearestBeacon.proximity;
        }
    }
}

- (void) yomeTapped:(UITapGestureRecognizer *)sender {
    [self updateYome:(_yomePhase + 1) % 4];
}

- (void) updateYome:(int)phase {
    _yomePhase = phase;
    _yomeImage.image = [UIImage imageNamed:YOME_IMAGE[_yomePhase]];
    AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:YOME_SPEECH[_yomePhase]];
    utterance.rate = 0.3f;
    utterance.pitchMultiplier = 1.4f;
    [_speechSynthesizer speakUtterance:utterance];
}

@end
````
AVSpeechSynthesizerいい感じです。rateやpitchMultiplierを微調整するのをお忘れなく！

それでは皆様、良いクリスマスを！