近接センサを使う
iPhoneの前カメラ付近にある近接センサに手や顔などを近づけるとアクションが起こるものです。
どうやら近接センサが物体を検知しているときは、デフォルトで画面が真っ暗になるようです。
しかも相当手を近づけないと反応しないので、距離を測ることができず使いどころが難しいかもしれません。
import UIKit class ViewController: UIViewController { @IBOutlet weak var sencerLabel: UILabel! @IBAction func sencerStop(sender: AnyObject) { //近接センサーのOFF myDevice.proximityMonitoringEnabled = false //近接センサーの監視を解除 NSNotificationCenter.defaultCenter().removeObserver(self, name:UIDeviceProximityStateDidChangeNotification, object: nil) } //UIDeviceクラスを呼ぶ let myDevice: UIDevice = UIDevice.currentDevice() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //近接センサーのON myDevice.proximityMonitoringEnabled = true //近接センサーの通知設定 NSNotificationCenter.defaultCenter() .addObserver( self, selector: "sencerAction:", name: "UIDeviceProximityStateDidChangeNotification", object: nil ) //近接センサーを通知する NSNotificationCenter.defaultCenter() .postNotificationName( "UIDeviceProximityStateDidChangeNotification", object: nil ) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } //近接センサの処理 func sencerAction(notification: NSNotification){ if myDevice.proximityState == true { //近づいた時 print("近づいた"); sencerLabel.text = "近づいた" }else{ //離れた時 print("離れた"); sencerLabel.text = "離れた" } } }
配列を検索する
配列にフィルタをかけたい場合は、こうなります。
let array = ["愛知", "北海道", "東京"] //北という文字が該当する場合 let arPredicate = NSPredicate(format: "self contains[c] '北'") //その要素を抜き出しなさい let arArray = (array as NSArray).filteredArrayUsingPredicate(arPredicate) println(arArray)
また、配列をplistに書いた場合は以下となります。
1.Supporting Filesを右クリックして、Property Listsを選択
2.RootのTypeをDictionaryからArrayに変える
3.Rootの右にある+ボタンを押してデータ追加
をした状態で、
// プロジェクトに保存されたプロパティリストのパスを取得する let filePath = NSBundle.mainBundle().pathForResource("sample", ofType: "plist") // データをプロパティリストから読み込む var array = NSArray(contentsOfFile: filePath!)! //NSArrayをArrayに変換 var arr: [String] = array as! [String] //Arrayを文字列に変換 let str = arr.reduce("") { $0 + String($1) } switch str.lowercaseString as NSString { case let str1 where str1.rangeOfString("名古屋").length != 0: println("あるよ") case let str1 where str1.rangeOfString("北海道").length != 0: println("さらにあるよ") default: println("ないよ") }
となります。
上記は条件分岐を使っていますが、単純にplistの該当データを抜き出したい場合は、
// プロジェクトに保存されたプロパティリストのパスを取得する let filePath = NSBundle.mainBundle().pathForResource("sample", ofType: "plist") // データをプロパティリストから読み込む var array = NSArray(contentsOfFile: filePath!)! //NSArrayをArrayに変換 var arr: [String] = array as! [String] //北という文字が該当する場合 let arPredicate = NSPredicate(format: "self contains[c] '北'") //その要素を抜き出しなさい let arArray = (arr as NSArray).filteredArrayUsingPredicate(arPredicate) println(arArray)
となります。
ランダムなタイミングで何かする・ランダムな間隔で何かする
ランダムなタイミングで何かすることと、ランダムな間隔で何かするというコードを書いてみました。
ランダムな間隔で何かする、のほうはわりと力技で、他に良い方法がある気がします。
まずランダムなタイミングで何かする。例えば、ボタンを押してからランダムなタイミングでイベントが起こるみたいな例です。
ボタンを設置しておいてから、結びつけておきます。
@IBAction func timeBtn(sender: AnyObject) { //0-30秒ランダム let random = arc4random() % 30 var doubleRandomNum: Double = Double(random) //遅らせる処理 let delay = doubleRandomNum * Double(NSEC_PER_SEC) var time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) dispatch_after(time, dispatch_get_main_queue(), { println( "ザ・ワールド" ) }) }
ランダムな間隔で何かするのほうです。1秒ごとにランダムな数値を吐き出し、条件分岐で処理を行わせることで
ランダムな間隔で文字を出力しています。
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //1秒ごとにupdate()の中身を繰り返し処理を行う var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("update"), userInfo: nil, repeats: true) } func update() { //0から10までのランダムな数値を出力=0から10秒までのランダムな時間を出力 let random2 = arc4random() % 10 switch random2 { //2秒のとき case 2: println("承太郎「そして時は動き出す」") //5秒のとき case 5: println("ディオ「そして時は動き出す」") default: //どこにも当てはまらない場合の処理、必ず書く break } }
しゃべらせつつ口パクアニメーション
Siriにしゃべらせつつ口パクアニメーションを同期させるのを試してみました。
とはいっても、母音に合わせてアニメーションの口を変える・・・などということはしていません(汗
本来はまばたきは目が開いている画像・半目の画像・閉じてる画像の3枚が良いのですが、サンプルで作ったものは人間キャラのアニメーションでは
なかったので、2枚にしてあります。
また、目を開いた状態・半目・閉じた状態の3つのアニメーションのタイミングを個々に細かく記述することが難しかったため、
力技でやっています。
いい方法があればご教授ください。
目を開いた状態・半目・閉じた状態のアニメーションを作る場合は、開いた状態が2秒・半目が0.1秒・閉じた状態が0.1秒くらいです。
なので今回は開いた状態が2秒・閉じた状態が0.2秒にしています。
準備:
1.まばたき用の静止画2枚(目が開いてる画像と閉じてる画像)・口パク静止画(口開けた画像と閉じた画像)を用意し、Imageviewを配置
2.AVFoundationのフレームワークを読み込ませておく
import UIKit import AVFoundation //SpeechSynthesizerクラス var talker = AVSpeechSynthesizer() class ViewController: UIViewController,AVSpeechSynthesizerDelegate { //Siriにしゃべらせる準備 var talker = AVSpeechSynthesizer() @IBOutlet weak var eyesOnPict: UIImageView! @IBOutlet weak var mousePict: UIImageView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //まばたきアニメーション 開いた状態が2秒・閉じた状態が0.2秒 //アニメーション画像の準備 var imgArray:[UIImage!] = [ UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormal.png"), UIImage(named: "BigeyeNormalZzz.png")] //アニメーション画像の設定 eyesOnPict.animationImages = imgArray //アニメーション全体の秒数 eyesOnPict.animationDuration = 2.2 //繰り返しは無限にするため0をセット eyesOnPict.animationRepeatCount = 0 //アニメーションスタート eyesOnPict.startAnimating() talker.delegate = self //口パクアニメーション //画像の準備 var imgArray2:[UIImage!] = [ UIImage(named: "mouse1.png"), UIImage(named: "mouse2.png")] //アニメーション画像の設定 mousePict.animationImages = imgArray2 //アニメーション全体の秒数 mousePict.animationDuration = 0.8 //繰り返しは無限にするため0をセット mousePict.animationRepeatCount = 0 speakBig() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } override func prefersStatusBarHidden() -> Bool { return true } //おしゃべりがスタートしたらどうするか func speechSynthesizer(synthesizer: AVSpeechSynthesizer!, didStartSpeechUtterance utterance: AVSpeechUtterance!) { //アニメーションスタート mousePict.startAnimating() } //おしゃべりが終わったらどうするか func speechSynthesizer(synthesizer: AVSpeechSynthesizer!, didFinishSpeechUtterance utterance: AVSpeechUtterance!) { // アニメーション終了 mousePict.stopAnimating() } func speakBig() { let speak1 = AVSpeechUtterance(string:"結局テクノロジーの歴史は欲の歴史なんだよねえ") // 言語を日本に設定 speak1.voice = AVSpeechSynthesisVoice(language: "ja-JP") //しゃべる速度 数値が大きくなるほど早い speak1.rate = 0.2 //声の高さ 数値が大きくなるほど高い speak1.pitchMultiplier = 0.4 // 実行 talker.speakUtterance(speak1) } }
OpenCVを使ってリアルタイムに顔認識
やはりリアルタイムに認識するのは重いですね。そりゃそうですよね、iPhoneだもの。
1.いつものようにプロジェクトファイルを作って、いったんXCodeを終了する
2.ターミナルを開き、以下を行う
[sudo] gem install cocoapodsと入力してリターンキーを押す
pod setupと入力してリターンキーを押す
3.いったんターミナルを終了する
4.ターミナルを開き、cdと入力した後にスペースを押す。そして1.のプロジェクトファイル(ファイル名.xcodeprojが入っているフォルダ)を
ドラッグ&ドロップする。そうするとパスが表示されます。そのままリターンキーを押す
5.pod initと入力
6.ターミナルを終了する。プロジェクトファイルが入ったフォルダの中にPodfileというファイルが出来ているので、それを
miなどのテキストエディタで開き、以下のように編集して保存する。
注:どうも2.4.10ではバグがあるようです。あとpod 'OpenCV'だけではダメで、バージョンも入れる必要があります
# Uncomment this line to define a global platform for your project # platform :ios, '8.0' target 'opencvTest4' do pod 'OpenCV', '2.4.9' end target 'opencvTest4Tests' do end
7.4.と同じ
8.pod installと入力し、リターンキーを押す
9.ファイル名.xcworkspaceをダブルクリックして開く
10.こちらを参照してファイルを作ったりコードを入力していく(ありがとうございます)
11.CameraUtil.swiftを以下のように書き換えたほうが良いっぽい
import Foundation import UIKit import AVFoundation class CameraUtil { // sampleBufferからUIImageへ変換 class func imageFromSampleBuffer(sampleBuffer: CMSampleBufferRef) -> UIImage { let imageBuffer: CVImageBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer) // ベースアドレスをロック CVPixelBufferLockBaseAddress(imageBuffer, 0) // 画像データの情報を取得 let baseAddress = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0) let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer) let width = CVPixelBufferGetWidth(imageBuffer) let height = CVPixelBufferGetHeight(imageBuffer) // RGB色空間を作成 let colorSpace = CGColorSpaceCreateDeviceRGB() // Bitmap graphic contextを作成 let bitsPerCompornent: UInt = 8 var bitmapInfo = CGBitmapInfo((CGBitmapInfo.ByteOrder32Little.rawValue | CGImageAlphaInfo.PremultipliedFirst.rawValue) as UInt32) let context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, bitmapInfo) // Quartz imageを作成 let imageRef = CGBitmapContextCreateImage(context) // ベースアドレスをアンロック CVPixelBufferUnlockBaseAddress(imageBuffer, 0) // UIImageを作成 let resultImage: UIImage = UIImage(CGImage: imageRef)! return resultImage } }
OpenCVを使う
Swift+iOSでOpenCVを使ってみます。
最初はcocoapodsをインストールしていたのですが、どうにもリンクエラーになってしまって
opencv2.frameworkを追加する以下のような方法でやることにしました。
1.こちらにアクセスし、
新しいバージョン(2015年6月の時点では3.0.0)をクリック、さらにopencv2.framework.zipをクリックし
ダウンロードする
2.プロジェクトファイルを作成し、プロジェクトファイルのLinked Fremeworks and Librariesに先ほど
ダウンロードし解凍したopencv2.frameworkをドラック&ドロップする
3.Fileメニュー→New→Fileを選択し、iOS-Source-Objective-C Fileを選ぶ。File typeはEmpty Fileにし、ファイル名を入力。
ここではTestOpenCVとします
4.ファイル名.mとプロジェクトファイル名-Bridging-Header.hができるので、ファイル名.mをファイル名.mmに書き換える
5.ファイル名.mmとプロジェクトファイル名-Bridging-Header.hにOpenCVのコードを書いていく
今回はこちらを参考にさせて頂いて、輪郭線を抽出するコードを書きます。
・プロジェクトファイル名-Bridging-Header.h
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface TestOpenCV : NSObject +(UIImage *)DetectEdgeWithImage:(UIImage *)image; @end
・ファイル名.mm
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #import "openCVTest2-Bridging-Header.h" #import <opencv2/opencv.hpp> #import <opencv2/imgcodecs/ios.h> @implementation TestOpenCV : NSObject +(UIImage *)DetectEdgeWithImage:(UIImage *)image{ //UIImageをcv::Matに変換 cv::Mat mat; UIImageToMat(image, mat); //白黒濃淡画像に変換 cv::Mat gray; cv::cvtColor(mat, gray, CV_BGR2GRAY); //エッジ検出 cv::Mat edge; cv::Canny(gray, edge, 200, 180); //cv::MatをUIImageに変換 UIImage *edgeImg = MatToUIImage(edge); return edgeImg; } @end
6.StoryboardにImageViewを設置し、画像を追加する
7.ViewControllerとImageeViewを結びつけ、以下のように入力する
import UIKit class ViewController: UIViewController { @IBOutlet weak var cvTestPic: UIImageView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //ここから追加 var image = cvTestPic.image var edge = TestOpenCV.DetectEdgeWithImage(image) cvTestPic.image = edge as UIImage; } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
追記あり;Bluetoothでデータ送受信
★
func peripheral(peripheral: CBPeripheral!, didWriteValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!) ...と
@IBAction func writeBtnTapped(sender: UIButton)...の項目を追加して、セントラル側からペリフェラル側へ
データを送れるようにしました。
これでペリフェラルとセントラルの双方でデータのやりとりができます。
Bluetoothでデータ送受信というと、画像などのメディアも送受信できるMultipeer Connectivityを使うのがスムーズなのかもですが、
どうやらCore Bluetoothのほうが電池をくわないそうなので、大変でしたがこっちで書いてみました。
こちらの本「iOS×BLE Core Bluetoothプログラミング」をベースにSwiftで書いています。
この本はとても素晴らしい本なのですが、Swiftでない部分もあるので、そこは補完しました。
まず最初にプロジェクトの設定画面でCoreBluetoothのFrameworkを読み込んでおきます。
Linked Frameworks and Librariesの+をクリックして、CoreBluetooth.Frameworkを選ぶだけ。
以下はペリフェラル(データ送る)側でボタンを押すとその値がセントラル(データ受信側)に送られて、
セントラル側でその値に応じたテキストとUIImageが表示されます。
ペリフェラル側でトリガーを送ってあげて、セントラル側でそのトリガーに合ったアクションが起きるという感じですね。
・ペリフェラル(データ送る)側
import UIKit import CoreBluetooth class ViewController: UIViewController, CBPeripheralManagerDelegate { @IBOutlet var advertiseBtn: UIButton! @IBOutlet var valueLabel: UILabel! @IBOutlet var strLabel: UILabel! var peripheralManager: CBPeripheralManager! var serviceUUID: CBUUID! var characteristic: CBMutableCharacteristic! var data:NSData! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. self.peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil) self.valueLabel.text = nil; } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func publishservice () { // サービスを作成 self.serviceUUID = CBUUID(string: "0000") let service = CBMutableService(type: serviceUUID, primary: true) // キャラクタリスティックを作成 let characteristicUUID = CBUUID(string: "0001") let properties = ( CBCharacteristicProperties.Notify | CBCharacteristicProperties.Read | CBCharacteristicProperties.Write) let permissions = ( CBAttributePermissions.Readable | CBAttributePermissions.Writeable) self.characteristic = CBMutableCharacteristic( type: characteristicUUID, properties: properties, value: nil, permissions: permissions) // キャラクタリスティックをサービスにセット service.characteristics = [self.characteristic] // サービスを Peripheral Manager にセット self.peripheralManager.addService(service) var msg: String = "0" let data: NSData! = msg.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion:true) println("data: \(data)") self.characteristic.value = data; } func startAdvertise() { // アドバタイズメントデータを作成する let advertisementData: Dictionary = [ CBAdvertisementDataLocalNameKey: "Test Device", CBAdvertisementDataServiceUUIDsKey: [self.serviceUUID] ] // アドバタイズ開始 self.peripheralManager.startAdvertising(advertisementData) self.advertiseBtn.setTitle("STOP ADVERTISING", forState: UIControlState.Normal) } func stopAdvertise () { // アドバタイズ停止 self.peripheralManager.stopAdvertising() self.advertiseBtn.setTitle("START ADVERTISING", forState: UIControlState.Normal) } //データ送信 func updateValueLabel () { let reportData = UnsafePointer<UInt8>(data.bytes) var bpm : UInt16 bpm = UInt16(reportData[0]) bpm = CFSwapInt16LittleToHost(bpm) let outputString = String(bpm) self.valueLabel.text = "分類用文字: \(outputString)" switch outputString { case "1": self.strLabel.text = "いちです" case "2": self.strLabel.text = "にです" case "3": self.strLabel.text = "さんです" default: self.strLabel.text = "その他" //ランダムな数値を出力する場合 //self.valueLabel.text = NSString(format: "Characteristic value: %@", self.characteristic.value) as String } } // ペリフェラルマネージャの状態が変化すると呼ばれる func peripheralManagerDidUpdateState(peripheral: CBPeripheralManager!) { println("state: \(peripheral.state)") switch peripheral.state { case CBPeripheralManagerState.PoweredOn: // サービス登録開始 self.publishservice() break default: break } } // サービス追加処理が完了すると呼ばれる func peripheralManager(peripheral: CBPeripheralManager!, didAddService service: CBService!, error: NSError!) { if (error != nil) { println("サービス追加失敗! error: \(error)") return } println("サービス追加成功!") // アドバタイズ開始 self.startAdvertise() } // アドバタイズ開始処理が完了すると呼ばれる func peripheralManagerDidStartAdvertising(peripheral: CBPeripheralManager!, error: NSError!) { if (error != nil) { println("アドバタイズ開始失敗! error: \(error)") return } println("アドバタイズ開始成功!") } // Readリクエスト受信時に呼ばれる func peripheralManager(peripheral: CBPeripheralManager!, didReceiveReadRequest request: CBATTRequest!) { println("Readリクエスト受信! requested service uuid:\(request.characteristic.service.UUID) characteristic uuid:\(request.characteristic.UUID) value:\(request.characteristic.value)") // プロパティで保持しているキャラクタリスティックへのReadリクエストかどうかを判定 if request.characteristic.UUID.isEqual(self.characteristic.UUID) { // CBMutableCharacteristicのvalueをCBATTRequestのvalueにセット request.value = self.characteristic.value; // リクエストに応答 self.peripheralManager.respondToRequest(request, withResult: CBATTError.Success) } } // Writeリクエスト受信時に呼ばれる func peripheralManager(peripheral: CBPeripheralManager!, didReceiveWriteRequests requests: [AnyObject]!) { println("\(requests.count) 件のWriteリクエストを受信!") for obj in requests { if let request = obj as? CBATTRequest { println("Requested value:\(request.value) service uuid:\(request.characteristic.service.UUID) characteristic uuid:\(request.characteristic.UUID)") if request.characteristic.UUID.isEqual(self.characteristic.UUID) { // CBCharacteristicのvalueに、CBATTRequestのvalueをセット self.characteristic.value = request.value; } } } // リクエストに応答 self.peripheralManager.respondToRequest(requests[0] as! CBATTRequest, withResult: CBATTError.Success) } // Notify開始リクエスト受信時に呼ばれる func peripheralManager(peripheral: CBPeripheralManager!, central: CBCentral!, didSubscribeToCharacteristic characteristic: CBCharacteristic!) { println("Notify開始リクエストを受信") println("Notify中のセントラル: \(self.characteristic.subscribedCentrals)") } // Notify停止リクエスト受信時に呼ばれる func peripheralManager(peripheral: CBPeripheralManager!, central: CBCentral!, didUnsubscribeFromCharacteristic characteristic: CBCharacteristic!) { println("Notify停止リクエストを受信") println("Notify中のセントラル: \(self.characteristic.subscribedCentrals)") } @IBAction func advertiseBtnTap(sender: UIButton) { if (!self.peripheralManager.isAdvertising) { self.startAdvertise() } else { self.stopAdvertise() } } @IBAction func updateBtn1(sender: UIButton) { // 新しい値となるNSDataオブジェクトを生成 //1の値を送ったとき let valuemoto = 1 let value = UInt8(valuemoto & 0xFF) data = NSData(bytes: [value] as [UInt8], length: 1) // 値を更新 self.characteristic.value = data; let result = self.peripheralManager.updateValue( data, forCharacteristic: self.characteristic, onSubscribedCentrals: nil) println("resultだよ: \(result)") self.updateValueLabel() } @IBAction func updateBtn2(sender: UIButton) { // 新しい値となるNSDataオブジェクトを生成 //2の値を送ったとき let valuemoto = 2 let value = UInt8(valuemoto & 0xFF) data = NSData(bytes: [value] as [UInt8], length: 1) // 値を更新 self.characteristic.value = data; let result = self.peripheralManager.updateValue( data, forCharacteristic: self.characteristic, onSubscribedCentrals: nil) println("resultだよ: \(result)") self.updateValueLabel() } @IBAction func updateBtn3(sender: UIButton) { // 新しい値となるNSDataオブジェクトを生成 //3の値を送ったとき let valuemoto = 3 let value = UInt8(valuemoto & 0xFF) data = NSData(bytes: [value] as [UInt8], length: 1) // 値を更新 self.characteristic.value = data; let result = self.peripheralManager.updateValue( data, forCharacteristic: self.characteristic, onSubscribedCentrals: nil) println("resultだよ: \(result)") self.updateValueLabel() } @IBAction func updateBtnRan(sender: UIButton) { //ランダムな値を送ったとき let value = UInt8(arc4random() & 0xFF) let data = NSData(bytes: [value] as [UInt8], length: 1) self.characteristic.value = data; let result = self.peripheralManager.updateValue( data, forCharacteristic: self.characteristic, onSubscribedCentrals: nil) println("resultだよ: \(result)") self.updateValueLabel() } }
・セントラル(データを受信してそのデータに応じたアクションが起きるようにした)側
//データ受信側 import UIKit import CoreBluetooth //プロパティ定義 class ViewController: UIViewController, CBCentralManagerDelegate,CBPeripheralDelegate { @IBOutlet weak var valueLabel: UILabel! @IBOutlet weak var pictNumLabel: UILabel! @IBOutlet weak var myimageView: UIImageView! var isScanning = false var centralManager: CBCentralManager! var peripheral: CBPeripheral! var characteristic:CBCharacteristic! var aCharacteristic: CBCharacteristic! var outputString:String! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //セントラルマネージャ初期化 self.centralManager = CBCentralManager(delegate: self, queue: nil) self.valueLabel.text = nil; } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } //データを表示 func updateValue() { var data2 = self.characteristic.value let reportData = UnsafePointer<UInt8>(data2.bytes) var bpm : UInt16 bpm = UInt16(reportData[0]) bpm = CFSwapInt16LittleToHost(bpm) let outputString = String(bpm) self.valueLabel.text = "文字変換: \(outputString)" switch outputString { case "1": pictNumLabel.text = "いちです" myimageView.image = UIImage(named: "testPic1.png") case "2": pictNumLabel.text = "にです" myimageView.image = UIImage(named: "testPic2.png") case "3": pictNumLabel.text = "さんです" myimageView.image = UIImage(named: "testPic3.png") case "4": pictNumLabel.text = "ランダム" myimageView.image = UIImage(named: "testPic4.png") default: pictNumLabel.text = "その他" myimageView.image = UIImage(named: "testPic1.png") } } //セントラルマネージャの状態が変化すると呼ばれる func centralManagerDidUpdateState(central: CBCentralManager!) { println("state: \(central.state)") } //周辺にあるデバイスを発見すると呼ばれる func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData: [NSObject : AnyObject]!, RSSI: NSNumber!) { println("発見したBLEデバイス: \(peripheral)") self.peripheral = peripheral self.peripheral = peripheral // 接続開始 self.centralManager.connectPeripheral(self.peripheral, options: nil) } // ペリフェラルへの接続が成功すると呼ばれる func centralManager(central: CBCentralManager!, didConnectPeripheral peripheral: CBPeripheral!) { println("接続成功!") // サービス探索結果を受け取るためにデリゲートをセット peripheral.delegate = self // サービス探索開始 peripheral.discoverServices(nil) } // ペリフェラルへの接続が失敗すると呼ばれる func centralManager(central: CBCentralManager!, didFailToConnectPeripheral peripheral: CBPeripheral!, error: NSError!) { println("接続失敗・・・") } func centralManager(central: CBCentralManager!,didDisconnectPeripheral peripheral:CBPeripheral!,error: NSError!) { println("接続が切断されました。") if error != nil { println("エラー: \(error)") } self.peripheral = nil; self.characteristic = nil; self.valueLabel.text = nil; } // サービス発見時に呼ばれる func peripheral(peripheral: CBPeripheral!, didDiscoverServices error: NSError!) { if error != nil { println("エラー: \(error)") return } let services: NSArray = peripheral.services println("\(services.count) 個のサービスを発見! \(services)") for obj in services { if let service = obj as? CBService { // キャラクタリスティック探索開始 peripheral.discoverCharacteristics(nil, forService: service) } } } // キャラクタリスティック発見時に呼ばれる func peripheral(peripheral: CBPeripheral!, didDiscoverCharacteristicsForService service: CBService!, error: NSError!) { if error != nil { println("エラー: \(error)") return } let characteristics: NSArray = service.characteristics println("\(characteristics.count) 個のキャラクタリスティックを発見! \(characteristics)") // 特定のキャラクタリスティックをプロパティに保持 let uuid = CBUUID(string:"0001") for aCharacteristic in characteristics { if aCharacteristic.UUID == uuid { self.characteristic = aCharacteristic as! CBCharacteristic break; } } } // Notify開始/停止時に呼ばれる func peripheral(peripheral: CBPeripheral!, didUpdateNotificationStateForCharacteristic characteristic:CBCharacteristic!, error: NSError!) { if error != nil { println("Notify状態更新失敗...error:%@", error) } else { println("Notify状態更新成功!characteristic UUID:\(characteristic.UUID), isNotifying: \(characteristic.isNotifying)") } } // データ更新時に呼ばれる func peripheral(peripheral: CBPeripheral!, didUpdateValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!) { if error != nil { println("データ更新通知エラー:%@", error) return } else { println("データ更新! characteristic UUID: \(characteristic.UUID), value: \(characteristic.value)") updateValue() } } func peripheral(peripheral: CBPeripheral!, didWriteValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!) { if error != nil { println("Write失敗...error:%@", error) } else { println("Write成功!") // このキャラクタリスティックの値には実はまだ更新が反映されていない updateValue() } } @IBAction func scanBtn(sender: UIButton) { if !isScanning { isScanning = true // スキャン開始(特定サービスを持つペリフェラルに限定) let serviceUUIDs:[AnyObject] = [CBUUID(string:"0000")] self.centralManager.scanForPeripheralsWithServices(serviceUUIDs, options: nil) sender.setTitle("STOP SCAN", forState: UIControlState.Normal) } else { // スキャン停止 self.centralManager.stopScan() sender.setTitle("START SCAN", forState: UIControlState.Normal) isScanning = false } } @IBAction func writeBtnTapped(sender: UIButton) { //13の値を送ったとき var valuemoto2 = 13 var value: UInt8 = UInt8(valuemoto2 & 0xFF) var data = NSData(bytes: [value] as [UInt8], length: 1) peripheral .writeValue(data, forCharacteristic: characteristic, type: CBCharacteristicWriteType.WithResponse) } @IBAction func notifyBtn1(sender: UIButton) { if !self.characteristic.isNotifying { // Notify開始をリクエスト self.peripheral .setNotifyValue(true, forCharacteristic: self.characteristic) sender.setTitle("STOP NOTIFY",forState:UIControlState.Normal) } else { // Notify停止をリクエスト self.peripheral .setNotifyValue(false, forCharacteristic: self.characteristic) sender.setTitle("START NOTIFY",forState:UIControlState.Normal) } } }