SlideShare ist ein Scribd-Unternehmen logo
1 von 99
プログラミングは楽し
Programming Is Fun
2016/11/6
Bitz Co., Ltd.
村上幸雄
村上幸雄
@m_yukio
ビッツ有限会社
http://www.bitz.co.jp/
スライド
http://www.slideshare.net/yukiomurakami
http://www.slideshare.net/secret/dgZ9zJsHhlFYmK
サンプルコード
https://github.com/murakami/TextToSpeech
https://github.com/murakami/Wibree
Cocoa勉強会
• 2003年から続く勉強会です
ここでmacOSやiOSのプログラミングを学びました
。
• イベント告知
• http://connpass.com/series/499/
• http://cocoa-study.connpass.com
• 関東第76回Cocoa勉強会
コピペで作るTheta sの制御ソフト
SwiftでのState Machineの実装方法
Swiftのオプショナルとはなんなのか?
• Cocoa Study at Ikebukuro #4
スピーチにエフェクトをかける
AppleScriptでPDFからテキストを抽出する
Extracting text from PDF
• Cocoa Study at Mated #2
MOSA自習室
• 今年度よりmacOSやiOS、watchOS、tvOSの技術的な話題を中
心として、定期的な自主学習の場を設けることとなりました。
• http://mosa.connpass.com
第1回は、7月11日(月)開催。
第2回は、8月8日(月)開催。
第3回は、9月5日(月)開催。
第4回は、10月14日(金)開催。
第5回は、11月25日(金)に開催予定です!
http://mosa.connpass.com/event/42888/
• 第3回MOSA自習室
談話と特殊効果
ライフゲーム
• 第4回MOSA自習室
Newt On Project Demo
ソフトウェア、ハードウェアの歴史から「一歩先」
を読む
第5回 MOSA自習室(11/25)で発表します!
Arduino Uno と IBM Bluemix を利用してクラウ
ド対応の温度センサーを作成する
今後について
• 基本的に、発表内容に制限はありませんので、その時の参加
者によって決まりますが、自分として構想です、
• 業務への関係が深い話題も取り上げたいと考えています
• 設計法。例えば、MVVMだとか、Swiftyだとか。
• CI。Jenkinsおじさん。ビルドや配信の自動化。
• UIViewやViewControllerの深層。
• Git Flow。Pull Requestどうしてます?
• よろず相談でもOK
• でも、いきなり長いソースコードを見せられても、
反応するが難しいので、connpassのフィードにコ
メントを投稿するなど、情報をアップしていただけ
れば
• できれば、困っていることを資料にして発表してい
ただけると、内容に興味を持った方のフォローが期
待できると思います!
Cocoa Advent Calendar 2016
• 今年もやります!
http://qiita.com/advent-calendar/2016/cocoa
• macOSやiOS、watchOS、tvOSのフレームワーク
であるCocoaのAdvent Calendarです。
• 投稿を募集しています。
自由に投稿してください。
Text to Speech
• アナウンサーにナレーションを頼むと高価。
• 安価に、パーソナルコンピュータの読み上げ機能で
ナレーションを録音。
• WWDCセッションで読み上げた音声にエフェクト
をかけるデモがあった。
• 例えば、ノイズ混じりのラジオ放送。
Speech Synthesis
文書を読み上げる
$ say -f ./風琴と魚の町.txt
Speech Synthesis framework
Speech Synthesizer
Core Audio
Using an NSSpeechSynthesizer object
- (id)init {
self = [super init];
if (self) {
synth = [[NSSpeechSynthesizer alloc] init]; //start with default voice
//synth is an ivar
[synth setDelegate:self];
}
return self;
}
- (IBAction)speak:(id)sender
{
NSString *text = [phraseField stringValue];
NSString *voiceID =[[NSSpeechSynthesizer availableVoices]
objectAtIndex:[voiceList indexOfSelectedItem]];
[synth setVoice:voiceID];
[synth startSpeakingString:text];
}
An implementation of speechSynthesizer:didFinishSpeaking:
- (void)speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:(BOOL)finishedSpeaking
{
[_textToSpeechExampleTextView setSelectedRange:_orgSelectionRange]; // Set selection length to zero.
[_textToSpeechExampleSpeakButton setTitle:@"Start Speaking"];
[_saveButton setTitle:@"Save As File..."];
[_textToSpeechExampleSpeakButton setEnabled:YES];
[_saveButton setEnabled:YES];
[_voicePop setEnabled:YES];
}
CocoaSpeechSynthesisExample
https://developer.apple.com/library/content/samplec
ode/CocoaSpeechSynthesisExample/Introduction/Int
ro.html
こちらはCore Foundationを使っていますね。
サンプルを
動かしてみましょう!
AULab
Mastered for iTunes
• 以前は、開発環境に付属するAudio Unitデバッグツー
ルと認識していましたが。。。
• http://www.apple.com/jp/itunes/mastered-for-itunes/
• AU Labは、Appleの無料のデジタルオーディオミキシングアプリケーションで、
Mastered for iTunesの新しいツールの一つであるAURoundTripAAC Audio Unitを
含む、Audio Unitエフェクトのホストアプリケーションとして使用できます。
LogicやそのほかのAudio Unitホストアプリケーションを持っていない方は、AU
Labをダウンロードすれば、オーディオのオーディション、ピークとクリッピン
グの検出、ダブルブラインドリスニングテストを始められます。
テキストをsayコマンドで読
み上げる
$ say -n : -f ./風琴と魚の町.txt
SAY(1) Speech Synthesis Manager SAY(1)
NAME
say - Convert text to audible speech
:
OPTIONS
:
-n name, --network-send=name
-n name:port, --network-send=name:port
-n :port, --network-send=:port
-n :, --network-send=:
Specify a service name (default "AUNetSend") and/or IP port to be
used for redirecting the speech output through AUNetSend.
:
AU Labを起動
AUNetReceiveを追加
接続
接続できない場合
AUDistortionを選択
AUBandpass バンドパスフィルタ 必要な範囲の周波数のみを通す。
AUDelay Appleディレイ 遅延。
AUDistortion ディストーション 歪ませる。
AUDynamicsProcessor ダイナミクスプロセッサ 音量、音圧を制御。
AUFilter フィルタ 成分を取り除く。
AUGraphicsEQ グラフィックイコライザ トーンコントロール。
AUHighShelfFilter ハイシェルフ・フィルタ カットオフ周波数以上の音声を増幅量分だけ増幅する。
AUHipass ハイパスフィルタ カットオフ周波数以上の音声のみを通す。
AULowpass ローパスフィルタ カットオフ周波数以下の音声のみを通す。
AULowShelfFilter ローシェルフ・フィルタ カットオフ周波数以下の音声を増幅量分だけ増幅する。
AUMatrixReverb 残音。
AUMultibandCompressor マルチバンドコンプレッサ 周波数ごとにコンプレッサがかけられる。
AUNBandEQ Nバンドイコライザ 音声信号の周波数特性を変更する。
AUNewPitch 振動間隔を変更して、音の高さを変える。
AUParametricEQ パラメトリックイコライザ 周波数以外も変更できる。
AUPeakLimiter ピークリミッタ ダイナミックレンジを制御する。
AUPitch ピッチ 振動間隔を変更して、音の高さを変える。
AUReverb2 残音。
AURogerBeep
AUSampleDelay
使ってみましょう!
Audio Unit
• 音声信号を処理するソフトウェアプラグイン。
• 単一のAudio Unitを複数のチャネルおよびアプリケ
ーションが同時に利用できる。
• システムが提供するAudio Unitやサードパーティが
提供するAudio Unitを使用できる。
Compressor unit
Pitch unit
Output unit
Instrument unit
Splitter unit
Filter unit Distortion unit
エフェクトユニット サブタイプ 説明
AUBandpass kAudioUnitSubType_BandPassFilter 1バンドのバンドパスフィルタ。
AUDynamicsProcessor kAudioUnitSubType_DynamicsProcessor ヘッドルーム、圧縮量、アタック時間、リリース時間などのパラメタ
を設定できるダイナミックプロセッサ。
AUDelay kAudioUnitSubType_Delay ディレイユニット。
AUFilter kAudioUnitSubType_AUFilter 5バンドフィルタ。高周波及び低周波のカットオフに加えて、3つの
バンドパスフィルタを使用できる。
AUGraphicsEQ kAudioUnitSubType_GraphicsEQ 10バンド又は31バンドのグラフィックイコライザ。
AUHiPass kAudioUnitSubType_HighPassFilter レゾナンスのピークを調整できるハイパスフィルタ。
AUHighShelfFilter kAudioUnitSubType_HighShelfFilter 高周波を固定量だけブースト又はカットできるフィルタ。
AUPeakLimiter kAudioUnitSubType_PeakLimiter ピークリミッタ。
AULowPass kAudioUnitSubType_LowPassFilter レゾナンスのピークを調整できるローパスフィルタ。
AULowShelfFilter kAudioUnitSubType_LowShelfFilter 低周波を固定量だけブースト又はカットできるフィルタ。
AUMultibandCompressor kAudioUnitSubType_MultiBandCompressor 4バンドコンプレッサ。
AUMatrixReverb kAudioUnitSubType_MatrixReverb ルームサイズや吸音特性等の空間特性を指定できるリバーブユニット
。
AUNetSend kAudioUnitSubType_NetSend オーディオデータをネットワーク経由でストリーミングするユニット
。AUNetReceiveジェネレータオーディオユニットと組み合わせて使
用する。
AUParametricEQ kAudioUnitSubType_ParametricEQ パラメトリックイコライザ。
AUSampleDelay kAudioUnitSubType_SampleDelay 時間でなくサンプル数でディレイを設定できるディレクユニット。
AUPitch kAudioUnitSubType_Pitch 再生速度を変化させずにサウンドのピッチを変更できるエフェクトユ
ニット。
Speech Synthesis
と
Audio Unit
SpeechSynthesis.h
/*------------------------------------------*/
/* AudioUnit constants - new in 10.5 */
/*------------------------------------------*/
enum {
kAudioUnitSubType_SpeechSynthesis = 'ttsp', /* kAudioUnitType_Generator */
kAudioUnitProperty_Voice = 3330, /* Get/Set (VoiceSpec) */
kAudioUnitProperty_SpeechChannel = 3331 /* Get (SpeechChannel) */
};
SpeechSynthesisもAudioUnitとして扱える。
AudioUnitの格納場所
• ~/Library/Audio/Plug-Ins/Components
• /Library/Audio/Plug-Ins/Components
• /System/Library/Components
AudioUnit一覧の取得
• CountComponentsで指定タイプの個数を取得。
• FindNextComponentで各Unitの情報を取得。
• ComponentDescription構造体からタイプとサブタ
イプ、製造元コードを取得。
• OpenComponentで各Unitを開き、各種プロパティ
情報を取得。
オーディオ処理グラフ
• NewAUGraphでグラフを作成。
• AUGraphNewNodeでAudioUnitをグラフに追加。
• グラフの終端は出力Unitにする。
• AUGraphConnectNodeInputでUnitを接続する。
• Unit追加後にAUGraphOpenを呼び出す。
• AUGraphInitializeで初期化。
• AUGraphStartで処理開始。
• AUGraphUninitializeで未初期化状態に戻せる。
• AUGraphCloseでUnitが解放。
• AUGraphDisposeでグラフ破棄。
ユーザインターフェイ
ス
• AULabが参考になる。
• Cocoaベースのインターフェイスの場合、Unitのプロパティ
kAudioUnitProperty_CocoaUIを問い合わせて、インターフェイス
を実装しているビューを見つけ、それのインスタンスを作成する
。
• Carbonベースのインターフェイスの場合、Component Manager
コンポーネントとして格納されている。識別子
kAudioUnitProperty_GetUIComponentListプロパティで取得し、
コンポーネントに対してAudioUnitCarbonViewCreateを呼び出し
てインスタンス化すると、HIViewとして表示される。
Demo
まとめ
• Speech Synthesisもユニット
• Audio Unitの動作確認は、AU Labで
• システムで用意しているAudio Unitの機能はヘッダ
ーファイルから知る
• 今回触れなかったが、Audio UnitはCocoaクラスが
用意された
すれ違い通信
• アプリケーション開発者にとって、すれ違い通信を
要求されることが多い機能ですね。
• AndroidでBluetoothペアリングから相手を特定した
機能を実装したことがあります。これは電池を食い
ました。
• Bluetooth LEで識別子を交換し、サーバ側で紹介す
るという機能を実装したこともありました。
• Bluetooth Low Energy (Bluetooth LE)のGATTプロ
ファイルでの通信
• Core Bluetoothフレームワーク
• iBeacon
• 位置情報サービス
Bluetooth LE
Bluetooth LEは、省電力な電波を使った無線通信で、
4.xでは対応機器は次の3つに分類されます。
分類 説明
Bluetooth Smart
4.0で追加されたBluetooth Low
Energyのみ対応。
Bluetooth Smart Ready
Bluetooth LEと従来のBluetoothの両
方に対応。
Bluetooth 従来のBluetoothのみ対応。
すれ違い通信
識別子 識別子
Periphera
l
Advertise
Central 発見
Service
UUID
Peripheralが対応しているService UUIDをAdvertiseする。
Centralは探しているService UUIDがないか調査する。
Centralが見つけられたら、Peripheralに対して接続要求を出し
、受けいれるとデータ通信が可能になる。
サンプルコードでは、識別子のCharacteristic UUIDを問い合わ
せて、識別子を受け取っている。
Service
すれ違い通信
Characteristic
識別子
CBPeripheral
CBCharacteristic
CBService
Core Bluetooth
Central Managerの起動
dispatch_queue_t dispatchQueue = dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
self.centralManager = [[CBCentralManager alloc]
initWithDelegate:self
queue:dispatchQueue];
• Central Managerは生成後、デリゲートオブジェクトの
centralManagerDidUpdateState: を呼び出します。
• サンプルでは、Central Managerを所有している
WibreeCentralResponseParserクラスをデリゲートオンジェク
トとして設定しています。
電源Onになったら、Peripheralを探す
- (void)centralManagerDidUpdateState:
(CBCentralManager *)central
{
if (central.state != CBManagerStatePoweredOn) {
return;
}
[self scan];
}
- (void)scan
{
NSArray<CBUUID *> *serviceUUIDs = @[
[CBUUID UUIDWithString:Document.WIBREE_SERVICE_UUID]];
NSDictionary<NSString *,id> *options = @{
CBCentralManagerScanOptionAllowDuplicatesKey : @YES };
[self.centralManager
scanForPeripheralsWithServices:serviceUUIDs
options:options];
}
探すサービスUUID
電源ON
• serviceUUIDsにnilを設定すると、見つけたペリフェラル全てを検出しますので
、ペリフェラルのデバッグに便利です。
Peripheralが見つかったので接続する
- (void)centralManager:(CBCentralManager *)central
didDiscoverPeripheral:(CBPeripheral *)peripheral
advertisementData:(NSDictionary *)advertisementData
RSSI:(NSNumber *)RSSI
{
if ((RSSI.integerValue > -15) || (RSSI.integerValue < -35))
return;
if (self.discoveredPeripheral != peripheral) {
self.discoveredPeripheral = peripheral;
[self.centralManager connectPeripheral:peripheral
options:nil];
[self.centralManager stopScan];
}
}
• ペリフェラルが検出されたら、省電力のため、ペリフェラルの走査は停止しま
す。
検出範囲を変更して
、動かしてみてくだ
さい。
接続したPeripheralのサービスを検索する
- (void)centralManager:(CBCentralManager *)central
didConnectPeripheral:(CBPeripheral *)peripheral
{
[self.data setLength:0];
peripheral.delegate = self;
[peripheral discoverServices:
@[[CBUUID UUIDWithString:
Document.WIBREE_SERVICE_UUID]]];
}
利用したいサービスのUUID
• 検索するサービスUUIDにnilを指定すると、提供する全てのサービスが検出でき
ますので、こちらもデバッグ用途で使えます。
サービス検出したので、特性を検索する
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
if (error) {
[self cleanup];
return;
}
NSArray<CBUUID *> *characteristicUUIDs = @[
[CBUUID UUIDWithString:
Document.WIBREE_CHARACTERISTIC_UUID]];
for (CBService *service in peripheral.services) {
[peripheral discoverCharacteristics:characteristicUUIDs
forService:service];
}
}
利用したいキャラクタリスティックスのUUID
• 検索するキャラクタリスティックスUUIDもnilを指定すると、提供する全ての特
性が検出できますので、デバッグ用途で使えます。
特性の検出後、値を取得する
- (void)peripheral:(CBPeripheral *)peripheral
didDiscoverCharacteristicsForService:(CBService *)service
error:(NSError *)error
{
if (error) {
[self cleanup];
return;
}
for (CBCharacteristic *characteristic
in service.characteristics) {
if ([characteristic.UUID isEqual:
[CBUUID UUIDWithString:Document.WIBREE_CHARACTERISTIC_UUID]]) {
[peripheral setNotifyValue:YES
forCharacteristic:characteristic];
}
}
}
特性の値の通知を設定
• 値が変化しないことが分かっている場合は、CBPeripheralクラスの
readValueForCharacteristic:メソッドでも行えます。
特性の値を受け取る
- (void)peripheral:(CBPeripheral *)peripheral
didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error
{
if (error) return;
NSString *stringFromData = [[NSString alloc]
initWithData:characteristic.value
encoding:NSUTF8StringEncoding];
if ([stringFromData isEqualToString:@"EOM"]) {
NSString *uniqueIdentifier = [[NSString alloc]
initWithData:self.data
encoding:NSUTF8StringEncoding];
dispatch_async(dispatch_get_main_queue(), ^{
[self _notifyParserDidDiscoverUUID:uniqueIdentifier];
});
[peripheral setNotifyValue:NO
forCharacteristic:characteristic];
[self.centralManager cancelPeripheralConnection:peripheral];
}
[self.data appendData:characteristic.value];
}
断片化された受信データを格納する
サンプルコードで決めた終端データを受け取る
通知の設定/解除の結果を受け取る
- (void)peripheral:(CBPeripheral *)peripheral
didUpdateNotificationStateForCharacteristic:
(CBCharacteristic *)characteristic
error:(NSError *)error
{
if (error) {
DBGMSG(@"Error changing notification state: %@",
error.localizedDescription);
}
if (![characteristic.UUID isEqual:[CBUUID
UUIDWithString:Document.WIBREE_CHARACTERISTIC_UUID]]) {
/* Exit if it's not the transfer characteristic */
return;
}
if (characteristic.isNotifying) {
DBGMSG(@"Notification began on %@", characteristic);
}
else {
[self.centralManager cancelPeripheralConnection:peripheral];
}
}
Peripheral Managerの起動
dispatch_queue_t dispatchQueue = dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
self.peripheralManager = [[CBPeripheralManager alloc]
initWithDelegate:self
queue:dispatchQueue
options:nil];
• Peripheral Managerは生成後、デリゲートオブジェクトの
peripheralManagerDidUpdateState: を呼び出します。
• サンプルでは、Peripheral Managerを所有している
WibreePeripheralResponseParserクラスをデリゲートオンジェ
クトとして設定しています。
Peripheral利用可能後にサービスと特性を設定
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
{
if (peripheral.state != CBManagerStatePoweredOn) {
return;
}
CBUUID *caracteristicUuid =
[CBUUID UUIDWithString:Document.WIBREE_CHARACTERISTIC_UUID];
self.transferCharacteristic = [[CBMutableCharacteristic alloc]
initWithType:caracteristicUuid
properties:CBCharacteristicPropertyNotify
value:nil
permissions:CBAttributePermissionsReadable];
CBUUID *serviceUuid = [CBUUID UUIDWithString:Document.WIBREE_SERVICE_UUID];
CBMutableService *transferService = [[CBMutableService alloc]
initWithType:serviceUuid primary:YES];
transferService.characteristics = @[self.transferCharacteristic];
[self.peripheralManager addService:transferService];
NSDictionary<NSString *,id> *advertisementData =
@{
CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:
Document.WIBREE_SERVICE_UUID]],
CBAdvertisementDataLocalNameKey : @"Wibree Peripheral"
};
[self.peripheralManager startAdvertising:advertisementData];
}
サービスUUID
キャラクタリスティックスUUID
ペリフェラルUUID
アドバタイズを開始
電源Onの判定
識別子の送信
- (void)peripheralManager:(CBPeripheralManager *)peripheral
central:(CBCentral *)central
didSubscribeToCharacteristic:(CBCharacteristic *)characteristic
{
self.dataToSend = [[Document sharedInstance].uniqueIdentifier dataUsingEncoding:NSUTF8StringEncoding];
self.sendDataIndex = 0;
[self sendData];
}
- (void)sendData
{
static BOOL sendingEOM = NO;
if (sendingEOM) {
BOOL didSend = [self.peripheralManager updateValue:[@"EOM" dataUsingEncoding:NSUTF8StringEncoding]
forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil];
if (didSend) {
sendingEOM = NO;
}
return;
}
if (self.sendDataIndex >= self.dataToSend.length) {
return;
}
BOOL didSend = YES;
while (didSend) {
NSInteger amountToSend = self.dataToSend.length - self.sendDataIndex;
if (amountToSend > NOTIFY_MTU) amountToSend = NOTIFY_MTU;
NSData *chunk = [NSData dataWithBytes:self.dataToSend.bytes+self.sendDataIndex length:amountToSend];
didSend = [self.peripheralManager updateValue:chunk forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil];
if (!didSend) {
return;
}
NSString *stringFromData = [[NSString alloc] initWithData:chunk encoding:NSUTF8StringEncoding];
self.sendDataIndex += amountToSend;
if (self.sendDataIndex >= self.dataToSend.length) {
sendingEOM = YES;
BOOL eomSent = [self.peripheralManager updateValue:[@"EOM" dataUsingEncoding:NSUTF8StringEncoding]
forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil];
if (eomSent) {
sendingEOM = NO;
}
return;
}
}
}
サンプルコードで決めた終端データを送る
バックグラウンドで動かすには
Info.plistのRequired background modesでApp communicates using CoreBluetoothを設定。
Info.plistのRequired background modesでApp shares data using CoreBluetoothを設定。
状態の保存と復元
• サンプルコードでは実装していませんが、
CoreBluetoothの保存/復元機能を使って、プロセス
が存在していない状態でも、CoreBluetoothのタス
クを実行するようにできます。
• iOS6から導入された状態の保存と復元に対応する
必要があります。サンプルでは、Documentクラス
の対応が必要でしょうか?
CBCentralManager初期化時に復元識別子を指定
self.centralManager = [[CBCentralManager alloc]
initWithDelegate:self
queue:dispatchQueue
options:@{
CBCentralManagerOptionRestoreIdentifierKey:
@"demo.Wibree.WibreeCentralResponseParser"}];
CBPeripheralManager初期化時に復元識別子を指定
self.peripheralManager = [[CBPeripheralManager alloc]
initWithDelegate:self
queue:dispatchQueue
options:@{
CBPeripheralManagerOptionRestoreIdentifierKey:
@"demo.Wibree.WibreePeripheralResponseParser"}];
復元識別子のリストを取得
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSArray *centralManagerIdentifiers =
launchOptions[
UIApplicationLaunchOptionsBluetoothCentralsKey];
NSArray *peripheralManagerIdentifiers =
launchOptions[
UIApplicationLaunchOptionsBluetoothPeripheralsKey];
• セントラル/ペリフェラルマネージャ初期化時に渡たす復元識別
子で再初期化されます。
• マネージャーが複数ある場合は、再初期化する復元識別子のリ
ストを取得して、再生成します。
復元デリゲートメソッド
- (void)centralManager:(CBCentralManager *)central
willRestoreState:(NSDictionary<NSString *,id> *)dict;
- (void)peripheralManager:(CBPeripheralManager *)peripheral
willRestoreState:(NSDictionary<NSString *,id> *)dict;
• 状態保存/復元機能を利用している場合、
centralManagerDidUpdateState: または
peripheralManagerDidUpdateState: の代わりに上記が呼ばれま
す。
インスタンスの状態を復元する
• 例えば、セントラルマネージャに検出されたペリフェラルのリ
ストを取得します。
- (void)centralManager:(CBCentralManager *)central
willRestoreState:(NSDictionary *)state
{
NSArray *peripherals =
state[CBCentralManagerRestoredStatePeripheralsKey];
初期化し直す
• 例えば、セントラルマネージャに検出されたペリフェラルのリ
ストを取得します。
- (void)centralManager:(CBCentralManager *)central
willRestoreState:(NSDictionary *)state
{
NSArray *peripherals =
state[CBCentralManagerRestoredStatePeripheralsKey];
続きを行う
• 例えば、検出済みのサービスを調べます。
NSUInteger serviceUUIDIndex =
[peripheral.services indexOfObjectPassingTest:
^BOOL(CBService *obj, NSUInteger index, BOOL *stop) {
return [obj.UUID isEqual:myServiceUUIDString];
}];
if (serviceUUIDIndex == NSNotFound) {
[peripheral discoverServices:@[myServiceUUIDString]];
Demo
うまく通信できない場合は、設定を確認してください。
アプリの構造について
• iOS開発を始めた際に、独学だったため、自分のス
タイルを得るため、他の方のスタイルを参考にさせ
ていただきました。
• 一つは、MVCのモデルに相当するクラスを用意す
ること。
• もう一つは、Connector/ResponseParserパターン
。
Document
Data Data Data Data
アプリケーションのデリゲートのインスタンス変数として保持する方法。
シングルトン
@interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
MyViewController *viewController;
MyDocument *document;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet MyViewController *viewController;
@property (nonatomic, retain) MyDocument *document;
@end
class Document: NSObject {
static let sharedInstance: Document = {
let instance = Document()
return instance
}()
}
• Connector/ResponseParserパターンは、HMDT木
下さんの『iOS開発におけるパターンによるオート
マティズム』で紹介されていたものです。
• 基本は並列に動く通信の管理ですが、タスク管理の
仕組みとして活用させてもらってます。
• 最新のCocoaのAPIでは不要になった部分もありま
すが、タスクの制御が行えるため、重宝しています
。
Connector parsers
ResponseParser
ResponseParser
requestWithParams:completionHandler:
ResponseParser生成 parsersに追加 処理完了 parsersから削除
• parsersに存在すれば、処理中。
• 同じインタフェースで異なる処理が扱える。
iBeacon
iBeaconを試してみる。
CoreBluetoothでビーコンを実装。
CoreLocationでビーコンを検出。
iBeaconはアドバタイズのパケットにiBeaconの情報を付与したもの
。
ビーコンUUIDというのを定義するので、これをサンプルのサービ
スUUIDとした。
ペリフェラルにメジャー番号とマイナー番号を与えられるので、サ
ンプルではこれを識別子とした。
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if (! self.locationManager) {
/* CLLocationManagerの初期化失敗 */
self.state = kBeaconCentralStateError;
self.error = [self _errorWithCode:
kBeaconCentralResponseParserGenericError
localizedDescription:
@"CLLocationManagerの初期化に失敗しました。"];
return;
}
CLLocationManagerを生成
• サンプルでは、CLLocationManagerを所有している
BeaconCentralResponseParserクラスをデリゲートオンジェク
トとして設定しています。
• 内部ではCoreBluetoothを呼び出していると思いますが、隠さ
れていて、便利に使えます。
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:
Document.BEACON_SERVICE_UUID];
self.beaconRegion = [[CLBeaconRegion alloc]
initWithProximityUUID:uuid
identifier:@"demo.Wibree.BeaconCentralResponseParser"];
if (! self.beaconRegion) {
self.state = kBeaconCentralStateError;
self.error = [self _errorWithCode:
kBeaconCentralResponseParserGenericError
localizedDescription:@"ビーコン領域の初期化に失敗しました。"];
self.locationManager = nil;
return;
}
ビーコン領域を生成
• ビーコン領域の観測を始めるための手続きです。
• 観測するビーコンのproximityUUIDを設定しています。
if (![CLLocationManager isMonitoringAvailableForClass:
[self.beaconRegion class]]) {
self.state = kBeaconCentralStateError;
self.error = [self _errorWithCode:
kBeaconCentralResponseParserGenericError
localizedDescription:
@"ビーコン領域の初期化に失敗しました。"];
self.locationManager = nil;
return;
}
ハードウェアのサポートのチェック
• iOS7以降では、領域の観測を行う前に呼び出す必要があります
。
[self.locationManager requestAlwaysAuthorization];
//[self.locationManager requestWhenInUseAuthorization];
CLAuthorizationStatus status = [CLLocationManager
authorizationStatus];
if ((status != kCLAuthorizationStatusAuthorizedAlways)
&& (status != kCLAuthorizationStatusAuthorizedWhenInUse)) {
self.state = kBeaconCentralStateError;
self.error = [self _errorWithCode:
kBeaconCentralResponseParserGenericError
localizedDescription:
@"ビーコン領域の初期化に失敗しました。"];
self.locationManager = nil;
return;
}
位置情報サービスの承認チェック
• iOS7以降では、領域の観測を行う前に呼び出す必要があります
。
• コードの位置としては検討の余地がありますが、位置情報サー
ビスの許可を求めるメッセージ表示のメソッド呼び出しも入れ
ています。
/* ビーコン領域の出入りを監視 */
[self.locationManager startMonitoringForRegion:self.beaconRegion];
/* 距離を監視 */
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
監視を開始
• サンプルでは、近接UUIDを指定していますが、メジャー値と
マイナー値も指定できます。
- (void)locationManager:(CLLocationManager *)manager
didEnterRegion:(CLRegion *)region
{
if ([self.delegate respondsToSelector:
@selector(beaconCentralResponseParser:didEnterRegion:)]) {
[self.delegate beaconCentralResponseParser:self
didEnterRegion:region];
}
}
- (void)locationManager:(CLLocationManager *)manager
didExitRegion:(CLRegion *)region
{
if ([self.delegate respondsToSelector:
@selector(beaconCentralResponseParser:didExitRegion:)]) {
[self.delegate beaconCentralResponseParser:self
didExitRegion:region];
}
}
領域の境界線横断イベント
• 領域に入った時と、領域から外れた際に呼ばれます。
- (void)locationManager:(CLLocationManager *)manager
didRangeBeacons:(NSArray *)beacons
inRegion:(CLBeaconRegion *)region
{
if ((! beacons) || (beacons.count == 0)) {
DBGMSG(@"%s 見つからない", __func__);
return;
}
DBGMSG(@"%s", __func__);
if ([self.delegate respondsToSelector:
@selector(beaconCentralResponseParser:didRangeBeacons:inRegion:)]) {
[self.delegate beaconCentralResponseParser:self
didRangeBeacons:beacons inRegion:region];
}
}
距離の変化を監視
- (void)locationManager:(CLLocationManager *)manager
monitoringDidFailForRegion:(CLRegion *)region
withError:(NSError *)error
{
DBGMSG(@"%s region:%@", __func__, region);
DBGMSG(@"%s error:%@", __func__, error);
}
領域指定失敗
• システム全体で利用可能な領域の総数は限られています。
• アプリケーションで同時に観測できる領域は20個。
• 領域登録の空きがないときに呼ばれます。
self.peripheralManager = [[CBPeripheralManager alloc]
initWithDelegate:self
queue:dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
if (! self.peripheralManager) {
self.state = kBeaconPeripheralStateError;
self.error = [self _errorWithCode:
kBeaconPeripheralResponseParserGenericError
localizedDescription:
@"CBPeripheralManagerの初期化に失敗しました。"];
return;
}
CBPeripheralManagerを生成
• iOSデバイスをiBeaconとして利用できます。
• ただし、アプリはフォアグラウンドで動作となります。
• つまり、テスト目的。
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:Document.BEACON_SERVICE_UU
self.beaconRegion = [[CLBeaconRegion alloc]
initWithProximityUUID:uuid
major:12
minor:34
identifier:@"demo.Wibree.BeaconCentralResponseParser"];
if (! self.beaconRegion) {
self.state = kBeaconPeripheralStateError;
self.error = [self _errorWithCode:
kBeaconPeripheralResponseParserGenericError
localizedDescription:
@"ビーコン領域の初期化に失敗しました。"];
self.peripheralManager = nil;
return;
}
ビーコン領域を生成
• ビーコンの識別子としてメジャー値とマイナー値を設定してい
ます。
- (void)peripheralManagerDidUpdateState:
(CBPeripheralManager *)peripheral
{
if (peripheral.state != CBManagerStatePoweredOn) {
return;
}
NSDictionary *dictionary = [self.beaconRegion
peripheralDataWithMeasuredPower:nil];
[self.peripheralManager startAdvertising:dictionary];
}
電源On検出後にアドバタイズ開始
• アドバタイズ開始は、電源On状態になったから実施してくださ
い。
バックグラウンドで動かすには
Info.plistのRequired background modesでlocationを設定。
• CoreBluetoothのバックグラウンド設定と衝突するようで、両
方は指定できないようです。
• iBeaconのペリフェラルは、フォアグラウンドのみですね。
Demo
BLEAD
BLEAD MC Light
1. BLEAD MC Lightアプリをダウンロードします。
2. BLEADのスイッチを押すと、アプリで検出できま
す。
3. ビーコンのUUIDを確認します。
4. Document.BEACON_SERVICE_UUID の値をビー
コンのUUIDに変更します。
Project Linking
• IoTサービス/IoTプラットフォーム
https://linkingiot.com
• Linking APIが公開されています。
https://linkingiot.com/developer/
まとめ
• iOSではCoreBluetoothでセントラルとペリフェラル
の両方が実装できます。
• ただ、動作させた結果から、一つのアプリ内で同時
に両方が並列で動作するわけではないようです。
• iBeaconを使えば、面倒くさい部分はフレームワー
ク側でやってくれますが、iBeaconで想定していな
い利用は難しいでしょう。
What's New in Xcode
App Signing
Best Practices
• Development
• Use automatic
• Add all developers to team
• Use the capabilities tab
• Manual
• Don’t set CODE_SIGN_IDENTITY
• Use the new general tab UI
• Use the capabilities tab
• Migrate to automatic
• Distribution
• Organizer

Weitere ähnliche Inhalte

Ähnlich wie Programming Is Fun

Audio Unit Extensions 〜オーディオエフェクトのアプリ間共有〜
Audio Unit Extensions 〜オーディオエフェクトのアプリ間共有〜Audio Unit Extensions 〜オーディオエフェクトのアプリ間共有〜
Audio Unit Extensions 〜オーディオエフェクトのアプリ間共有〜Shuichi Tsutsumi
 
オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!
オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!
オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!Masaki Muranaka
 
パワーユーザー必携の海外の拡張機能20選+α
パワーユーザー必携の海外の拡張機能20選+αパワーユーザー必携の海外の拡張機能20選+α
パワーユーザー必携の海外の拡張機能20選+αAkira Maruyama
 
IoTアプリ/ロボット開発をリアルタイムOSでレベルアップしませんか? ~高品質な組込み向けオープンソースを開発するTOPPERSプロジェクトのご紹介~
IoTアプリ/ロボット開発をリアルタイムOSでレベルアップしませんか? ~高品質な組込み向けオープンソースを開発するTOPPERSプロジェクトのご紹介~IoTアプリ/ロボット開発をリアルタイムOSでレベルアップしませんか? ~高品質な組込み向けオープンソースを開発するTOPPERSプロジェクトのご紹介~
IoTアプリ/ロボット開発をリアルタイムOSでレベルアップしませんか? ~高品質な組込み向けオープンソースを開発するTOPPERSプロジェクトのご紹介~Hideki Takase
 
東京工業大学「ロボット技術・ロボットミドルウェア」
東京工業大学「ロボット技術・ロボットミドルウェア」東京工業大学「ロボット技術・ロボットミドルウェア」
東京工業大学「ロボット技術・ロボットミドルウェア」NoriakiAndo
 
ヌーラボのサービス開発の裏側公開しちゃいます
ヌーラボのサービス開発の裏側公開しちゃいますヌーラボのサービス開発の裏側公開しちゃいます
ヌーラボのサービス開発の裏側公開しちゃいますikikko
 
ABEMA の視聴品質向上戦術
ABEMA の視聴品質向上戦術ABEMA の視聴品質向上戦術
ABEMA の視聴品質向上戦術Yusuke Goto
 
OSSを利用したプロジェクト管理
OSSを利用したプロジェクト管理OSSを利用したプロジェクト管理
OSSを利用したプロジェクト管理Tadashi Miyazato
 
2014年を振り返る 今年の技術トレンドとDockerについて
2014年を振り返る 今年の技術トレンドとDockerについて2014年を振り返る 今年の技術トレンドとDockerについて
2014年を振り返る 今年の技術トレンドとDockerについてMasahito Zembutsu
 
Azure DevOps で始めるスタートダッシュ
Azure DevOps で始めるスタートダッシュAzure DevOps で始めるスタートダッシュ
Azure DevOps で始めるスタートダッシュYasuaki Matsuda
 
ROBOMECH2021 RTMオンライン講習会 第1部
ROBOMECH2021 RTMオンライン講習会 第1部ROBOMECH2021 RTMオンライン講習会 第1部
ROBOMECH2021 RTMオンライン講習会 第1部openrtm
 
フィジカルコンピューティング入門 USB-MIDIベースのPepper-Monakaを使う
フィジカルコンピューティング入門  USB-MIDIベースのPepper-Monakaを使うフィジカルコンピューティング入門  USB-MIDIベースのPepper-Monakaを使う
フィジカルコンピューティング入門 USB-MIDIベースのPepper-Monakaを使うYoshitaka Kuwata
 
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術Unity Technologies Japan K.K.
 
Master-Detail App を実装する
Master-Detail App を実装するMaster-Detail App を実装する
Master-Detail App を実装する幸雄 村上
 
PythonとRによるデータ分析環境の構築と機械学習によるデータ認識
PythonとRによるデータ分析環境の構築と機械学習によるデータ認識PythonとRによるデータ分析環境の構築と機械学習によるデータ認識
PythonとRによるデータ分析環境の構築と機械学習によるデータ認識Katsuhiro Morishita
 
Eclipse PDT + MakeGoodによるPHPコードのテスト
Eclipse PDT + MakeGoodによるPHPコードのテストEclipse PDT + MakeGoodによるPHPコードのテスト
Eclipse PDT + MakeGoodによるPHPコードのテストAtsuhiro Kubo
 

Ähnlich wie Programming Is Fun (20)

Audio Unit Extensions 〜オーディオエフェクトのアプリ間共有〜
Audio Unit Extensions 〜オーディオエフェクトのアプリ間共有〜Audio Unit Extensions 〜オーディオエフェクトのアプリ間共有〜
Audio Unit Extensions 〜オーディオエフェクトのアプリ間共有〜
 
オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!
オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!
オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!
 
パワーユーザー必携の海外の拡張機能20選+α
パワーユーザー必携の海外の拡張機能20選+αパワーユーザー必携の海外の拡張機能20選+α
パワーユーザー必携の海外の拡張機能20選+α
 
Spring social の基礎
Spring social の基礎Spring social の基礎
Spring social の基礎
 
Osc tokyo20141019
Osc tokyo20141019Osc tokyo20141019
Osc tokyo20141019
 
IoTアプリ/ロボット開発をリアルタイムOSでレベルアップしませんか? ~高品質な組込み向けオープンソースを開発するTOPPERSプロジェクトのご紹介~
IoTアプリ/ロボット開発をリアルタイムOSでレベルアップしませんか? ~高品質な組込み向けオープンソースを開発するTOPPERSプロジェクトのご紹介~IoTアプリ/ロボット開発をリアルタイムOSでレベルアップしませんか? ~高品質な組込み向けオープンソースを開発するTOPPERSプロジェクトのご紹介~
IoTアプリ/ロボット開発をリアルタイムOSでレベルアップしませんか? ~高品質な組込み向けオープンソースを開発するTOPPERSプロジェクトのご紹介~
 
東京工業大学「ロボット技術・ロボットミドルウェア」
東京工業大学「ロボット技術・ロボットミドルウェア」東京工業大学「ロボット技術・ロボットミドルウェア」
東京工業大学「ロボット技術・ロボットミドルウェア」
 
ヌーラボのサービス開発の裏側公開しちゃいます
ヌーラボのサービス開発の裏側公開しちゃいますヌーラボのサービス開発の裏側公開しちゃいます
ヌーラボのサービス開発の裏側公開しちゃいます
 
ABEMA の視聴品質向上戦術
ABEMA の視聴品質向上戦術ABEMA の視聴品質向上戦術
ABEMA の視聴品質向上戦術
 
OSSを利用したプロジェクト管理
OSSを利用したプロジェクト管理OSSを利用したプロジェクト管理
OSSを利用したプロジェクト管理
 
RUDP
RUDPRUDP
RUDP
 
2014年を振り返る 今年の技術トレンドとDockerについて
2014年を振り返る 今年の技術トレンドとDockerについて2014年を振り返る 今年の技術トレンドとDockerについて
2014年を振り返る 今年の技術トレンドとDockerについて
 
Azure DevOps で始めるスタートダッシュ
Azure DevOps で始めるスタートダッシュAzure DevOps で始めるスタートダッシュ
Azure DevOps で始めるスタートダッシュ
 
ROBOMECH2021 RTMオンライン講習会 第1部
ROBOMECH2021 RTMオンライン講習会 第1部ROBOMECH2021 RTMオンライン講習会 第1部
ROBOMECH2021 RTMオンライン講習会 第1部
 
フィジカルコンピューティング入門 USB-MIDIベースのPepper-Monakaを使う
フィジカルコンピューティング入門  USB-MIDIベースのPepper-Monakaを使うフィジカルコンピューティング入門  USB-MIDIベースのPepper-Monakaを使う
フィジカルコンピューティング入門 USB-MIDIベースのPepper-Monakaを使う
 
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術
 
Master-Detail App を実装する
Master-Detail App を実装するMaster-Detail App を実装する
Master-Detail App を実装する
 
PythonとRによるデータ分析環境の構築と機械学習によるデータ認識
PythonとRによるデータ分析環境の構築と機械学習によるデータ認識PythonとRによるデータ分析環境の構築と機械学習によるデータ認識
PythonとRによるデータ分析環境の構築と機械学習によるデータ認識
 
Eclipse PDT + MakeGoodによるPHPコードのテスト
Eclipse PDT + MakeGoodによるPHPコードのテストEclipse PDT + MakeGoodによるPHPコードのテスト
Eclipse PDT + MakeGoodによるPHPコードのテスト
 
Androidテスティング実践2 システムテスト編
Androidテスティング実践2 システムテスト編Androidテスティング実践2 システムテスト編
Androidテスティング実践2 システムテスト編
 

Mehr von 幸雄 村上

アプリケーション識別子.pdf
アプリケーション識別子.pdfアプリケーション識別子.pdf
アプリケーション識別子.pdf幸雄 村上
 
圧縮ネイティブ・ライブラリについて.pdf
圧縮ネイティブ・ライブラリについて.pdf圧縮ネイティブ・ライブラリについて.pdf
圧縮ネイティブ・ライブラリについて.pdf幸雄 村上
 
分散環境におけるジャストインタイム設定の試み
分散環境におけるジャストインタイム設定の試み分散環境におけるジャストインタイム設定の試み
分散環境におけるジャストインタイム設定の試み幸雄 村上
 
SwiftのOptionalを理解する
SwiftのOptionalを理解するSwiftのOptionalを理解する
SwiftのOptionalを理解する幸雄 村上
 
え!それって参照渡し?
え!それって参照渡し?え!それって参照渡し?
え!それって参照渡し?幸雄 村上
 
プライバシーとセキュリティ(リモート通知のデバイストークンの扱いなど)
プライバシーとセキュリティ(リモート通知のデバイストークンの扱いなど)プライバシーとセキュリティ(リモート通知のデバイストークンの扱いなど)
プライバシーとセキュリティ(リモート通知のデバイストークンの扱いなど)幸雄 村上
 
AppleScriptとは何ぞや
AppleScriptとは何ぞやAppleScriptとは何ぞや
AppleScriptとは何ぞや幸雄 村上
 
Web API 通信の符号化について
Web API 通信の符号化についてWeb API 通信の符号化について
Web API 通信の符号化について幸雄 村上
 
SwiftのOptionalを理解する
SwiftのOptionalを理解するSwiftのOptionalを理解する
SwiftのOptionalを理解する幸雄 村上
 
Getting a packet trace
Getting a packet traceGetting a packet trace
Getting a packet trace幸雄 村上
 
The Bash in Tokyo : AppKitとUIKit
The Bash in Tokyo : AppKitとUIKitThe Bash in Tokyo : AppKitとUIKit
The Bash in Tokyo : AppKitとUIKit幸雄 村上
 
Swiftでブロックチェーンを実装する
Swiftでブロックチェーンを実装するSwiftでブロックチェーンを実装する
Swiftでブロックチェーンを実装する幸雄 村上
 
ゲームの企画書づくりに挑戦
ゲームの企画書づくりに挑戦ゲームの企画書づくりに挑戦
ゲームの企画書づくりに挑戦幸雄 村上
 
IBM Watson Services for Core ML
IBM Watson Services for Core MLIBM Watson Services for Core ML
IBM Watson Services for Core ML幸雄 村上
 
独自Documentクラス
独自Documentクラス独自Documentクラス
独自Documentクラス幸雄 村上
 
独自Documentクラス
独自Documentクラス独自Documentクラス
独自Documentクラス幸雄 村上
 
Document based application
Document based applicationDocument based application
Document based application幸雄 村上
 

Mehr von 幸雄 村上 (20)

アプリケーション識別子.pdf
アプリケーション識別子.pdfアプリケーション識別子.pdf
アプリケーション識別子.pdf
 
圧縮ネイティブ・ライブラリについて.pdf
圧縮ネイティブ・ライブラリについて.pdf圧縮ネイティブ・ライブラリについて.pdf
圧縮ネイティブ・ライブラリについて.pdf
 
分散環境におけるジャストインタイム設定の試み
分散環境におけるジャストインタイム設定の試み分散環境におけるジャストインタイム設定の試み
分散環境におけるジャストインタイム設定の試み
 
SwiftのOptionalを理解する
SwiftのOptionalを理解するSwiftのOptionalを理解する
SwiftのOptionalを理解する
 
え!それって参照渡し?
え!それって参照渡し?え!それって参照渡し?
え!それって参照渡し?
 
プライバシーとセキュリティ(リモート通知のデバイストークンの扱いなど)
プライバシーとセキュリティ(リモート通知のデバイストークンの扱いなど)プライバシーとセキュリティ(リモート通知のデバイストークンの扱いなど)
プライバシーとセキュリティ(リモート通知のデバイストークンの扱いなど)
 
AppleScriptなど
AppleScriptなどAppleScriptなど
AppleScriptなど
 
MojaveのDark Mode
MojaveのDark ModeMojaveのDark Mode
MojaveのDark Mode
 
AppleScriptとは何ぞや
AppleScriptとは何ぞやAppleScriptとは何ぞや
AppleScriptとは何ぞや
 
Web API 通信の符号化について
Web API 通信の符号化についてWeb API 通信の符号化について
Web API 通信の符号化について
 
SwiftのOptionalを理解する
SwiftのOptionalを理解するSwiftのOptionalを理解する
SwiftのOptionalを理解する
 
Getting a packet trace
Getting a packet traceGetting a packet trace
Getting a packet trace
 
The Bash in Tokyo : AppKitとUIKit
The Bash in Tokyo : AppKitとUIKitThe Bash in Tokyo : AppKitとUIKit
The Bash in Tokyo : AppKitとUIKit
 
Swiftでブロックチェーンを実装する
Swiftでブロックチェーンを実装するSwiftでブロックチェーンを実装する
Swiftでブロックチェーンを実装する
 
ゲームの企画書づくりに挑戦
ゲームの企画書づくりに挑戦ゲームの企画書づくりに挑戦
ゲームの企画書づくりに挑戦
 
IBM Watson Services for Core ML
IBM Watson Services for Core MLIBM Watson Services for Core ML
IBM Watson Services for Core ML
 
独自Documentクラス
独自Documentクラス独自Documentクラス
独自Documentクラス
 
独自Documentクラス
独自Documentクラス独自Documentクラス
独自Documentクラス
 
Bukuro.makers
Bukuro.makersBukuro.makers
Bukuro.makers
 
Document based application
Document based applicationDocument based application
Document based application
 

Kürzlich hochgeladen

デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)UEHARA, Tetsutaro
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfFumieNakayama
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...博三 太田
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineerYuki Kikuchi
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NTT DATA Technology & Innovation
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?akihisamiyanaga1
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)Hiroshi Tomioka
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfFumieNakayama
 

Kürzlich hochgeladen (8)

デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
 

Programming Is Fun