投稿

2014の投稿を表示しています

Unmanaged Objects

Swiftはいろいろと新しい設計がしてあって便利なんだけど、既存のものとの互換性という点で困ることがよくある。今回の内容もそのひとつ。メソッドの実行結果としてCore Foundationを受け取ってしまったとき。
返されたCore Foundationオブジェクトはおそらくメモリ管理がされていないUnmanaged<T>という型(?)となっている。Swiftはこのままでは使うことが出来ず、プログラマがこれをretainタイプ(CF_RETURNS_RETAINED)か非retainタイプ(CF_RETURNS_NOT_RETAINED)に決定してやる必要がある。これをするにはそのオブジェクトに対して
takeUnretainedValue()か
takeRetainedValue()を実行してやる。

説明に載っていた使用例は以下の通り
func StringByAddingTwoStrings(CFString!, CFString!) -> Unmanaged<CFString>!let memoryManagedResult = StringByAddingTwoStrings(str1, str2).takeUnretainedValue()
ポイントはretainタイプか非retainタイプかをどう判断すればいいのかということ。自分のプログラム内での使われ方から判断し、retainが必要ならretainすればいいのかなと思うのだが、今後の課題。

AVAudioSession細かいことまとめ(late 2014)

以前も書きました「AudioSessionの細かいことまとめ」のlate 2014版を書きます。

個人的なあらすじ以前アプリを作る際に、AudioSession(C言語)とAVAudioSession(Obj-C)のどちらを使おうかと検討したことがありました。そのときはAVAudioSession(Obj-C)の方に機能が足りない部分が多少あって、これは主流にならないのではと思い、AudioSession(C言語)の方で実装しました。しかし予想は外れ、AudioSession(C言語)の方がiOS7より非推奨となったので、今回改めてAVAudioSession(Obj-C)の方でまとめてみます。せっかくなのでSwiftの方も併記して書いてみようと思います。基本的にAVAudioSessionのクラスリファレンスを読んでまとめるだけなので詳しく知りたいことがある場合はそちらを見て下さい。
ちなみに作っているアプリはSilentBonusTrackというカセットテープアプリで、iPodのような音楽再生機能が中心となっています。私の興味の対象はその辺の音楽再生系が中心になります。

重要な項目まずは音を扱う場合には目を通しておく必要があるAudioSession関係です。

importするもの//Swift import AVFoundation //Objective-C #import <AVFoundation/AVFoundation.h>
インスタンスの取得このインスタンスに対して音の扱いに関するいろいろなメソッドを実行出来ます。
//Swift let session: AVAudioSession = AVAudioSession.sharedInstance() //Objective-C AVAudioSession *audioSession = [AVAudioSession sharedInstance]; Swiftの方はもしvarにする必要があればvarにしてください。

カテゴリーの指定アプリの音の扱い方法を数パターンの中から選んで指定します。
//Swift var error: NSError? session.setCategory(AVAudioSessionCategoryPlayback,error:&error) //O…

AVMIDIPlayer

iOSのAPIの中にAVMIDIPlayerというものを発見。これは音楽ファイルを再生するもので、対象フォーマットはMIDIとiMelody。iMelodyというのは着メロのような単音の音楽を扱うものらしい。所属はAVFoundationでiOS 8より追加になった。

初期化メソッドは2つ。
initWithContentsOfURL: soundBankURL: error:
initWithData: soundBankURL: error:
上のメソッドでは1つ目の引数はファイルのURLを渡し、2つ目の引数でsoundBankというもののURLを渡す。2つ目のsoundBankURLだが、これは再生に使う音源の指定でSoundFont2かDLS bank(のURL)を指定する。OS Xではnilが可能だが、iOSではnilはだめ。
下のメソッドでは1つ目の引数はNSDataインスタンス(の形式にした音楽ファイル)を渡す。2つ目以降は上のと同じ。
SoundFont2は音色のデータフォーマット。世の中でよく(?)使われている。DLSも音色のデータフォーマットだがSoundFont2の方がメジャー。

再生データ(第一引数)と音色データ(第二引数)の違いがややこしいと思う。音色データにはいろいろな音色のいろいろな音程の音が含まれている。それをどのタイミングでどの音を鳴らすかを指定するのが再生データ。

再生関係メソッドは普通に
play:
stop
prepareToPlay
playの引数で再生完了時に実行する処理を渡せる

プロパティは
playing (再生中かどうか readOnly)
duration (全体の時間 readOnly)
currentPosition (現在ポジション 読み書き可能)
そのほかに、MIDIらしく
rate (再生速度、1.0が標準 読み書き可能)
というものがある。

手持ちのMIDIファイルとダウンロードしたSoundFontで鳴らしてみたらiPad mini 2から音が出ました。まあ普通に再生出来ています。複数チャンネルにも対応しています。
しかしこうなるとiOSに初めから手頃な音源が搭載されていて欲しくなります。

SwiftのNSNumberでの符号なし整数の扱い

(追記 2015/10/22)
Xcode7.1出ました。修正されました。
リリースノートには

The NSNumberunsignedIntegerValue property now has the type UInt instead of Int, as do other methods and properties that use the NSUInteger type in Objective-C and whose names contain "unsigned..".
Most other uses of NSUInteger in system frameworks are imported as Int as they were in Xcode 7. (19134055)


と書かれています。
NSNumberは無事
public init(unsignedInteger value: UInt) public var unsignedIntegerValue: UInt { get } に変更されました。

(追記 2015/9/25)
Xcode7.1より修正されるようです。


【Xcode 6.1】
SwiftのNSNumberではUIntとなりそうなところでなぜかIntが定義されています。
具体的には初期化メソッドの
init(unsignedInteger value: Int) と値取り出しの
var unsignedIntegerValue: Int { get } です。
間違いかと思ったのですが、両方で同じように変わっているのでわざとかなという気もします。

参考までにNSNumberで扱われているその他の型がObjective-CとSwiftでどう対応しているかは

BOOL(Objective-C)
Bool(Swift)

char(Objective-C)
Int8(Swift)

double(Objective-C)
Double(Swift)

float(Objective-C)
Float(Swift)

int(Objective-C)
Int32(Swift)
どちらも32

NSInteger(Objective-C)
Int(Swift)
どちらも32環境で32、64環境で64

long long(Obje…

iOS8のTabViewControllerでのViewがLoadされるタイミング

iOS8ではViewがLoadのされるタイミングが少し変更されているようです。

以下の記事ではSegue実行時の流れを調べました。
http://samekard.blogspot.jp/2012/03/storyboard.html
この記事では次のように書きました。

1 performSegueWithIdentifier開始
2 新しいViewControllerのインスタンス化(initなど)
3 prepareForSegue開始
4 prepareForSegue終了
5 UIKitのインスタンス化、画面回転メソッドの呼び出し、viewDidLoadなど
6 performSegueWithIdentifier終了

iOS8でも移行先のViewControllerがシンプルなものであればこの通りなのですが、TabBarControllerの初めに表示されるViewControllerの場合はこのようになります。
4 prepareForSegue終了
5 performSegueWithIdentifier終了
6 UIKitのインスタンス化、画面回転メソッドの呼び出し、viewDidLoadなど
(2番目移行に表示されるViewControllerは表示の直前でViewをLoadします)

TabViewControllerに乗っている各ViewControllerのViewはperformSegueWithIdentifierより後でインスタンス化するようです。ちなみにViewController自体は2の時点でインスタンス化されます。

Swift資料の英単語 - Language Guide

実際に資料を読みながらわからなかった単語を記載していく。
英語は得意というわけではないので若干の誤りがあるかもしれない。
本文に合わせて多少変更した意味になっているところもある。
Language Guideの範囲です。
また、各項目について簡単なまとめも書きます(ほぼ自分用)。

The Basics難易度★★★☆☆
まあ基本

Nonetheless それにもかかわらず
its own versions / Swiftの中であらためて定義されている?
fundamental 基本的な、根本的な
textual 言葉通りの
extensive 広範囲の
to store and refer to / to storeと to refer to
in intent 意図的に?
compound 複合物
absence 不在
an example 一つの例
prevents A from B / AがBするのを防ぐ
restriction 制限

Constants and Variablesassociate A with B / AとBを結びつけて考える
once いったん…すると
whereas その一方で
attempt 試み
Type Annotations 型の指定
in practice 実のところ
A rather than B / BではなくてA (「むしろ」のような中途半端な表現がいらないような)
Unicode characters 文字のキャラクターと動物のキャラクターをかけたダジャレ?
否定文 Nor 倒置した肯定文 / 両方否定
Unlike 〜と違って
appropriate 適切な
interpolation 書き込まれた語句
prompt A to do / 〜するようにそくす

Semicolonsalthough 〜 / 〜けど

Integersfractional 微量の、少数の
convention しきたり
capitalized 大文字で始める
Bound 境界
appropriate-sized ふさわしいサイズの
therefore したがって
alongside といっしょに (同じタイプ同士ならキャストの必要がないという意味?)
consistency 一貫性 (なんのことやらわからない)
interoperability 相互…

日本シリーズの確率問題を考える

イメージ
【受験生に問題】(1)日本シリーズのある試合で阪神が勝ったことを知りましたが、それが第何戦かは分かりません。他の試合の結果も分かりません。阪神が日本一になる確率は何でしょう?(2)その後、それが第5戦であることを知りました。阪神が日本一になる確率は何でしょう?(勝率は5割とする)
— Masahiro Ono (@masahiro_ono) 2014, 10月 21
出題しておいてなんだけど、(1)はえぐいな・・・。
— Masahiro Ono (@masahiro_ono) 2014, 10月 21
先の問題の(1)の設定に曖昧さがありました。a)おもむろにテレビをつけてひとつの試合の結果を知ったケースと、b)シリーズ終了後に友達がランダムに一つの試合の結果を教えてくれたケースで、答えが違うはず。それぞれいくつでしょう? @kisshi_ku
— Masahiro Ono (@masahiro_ono) 2014, 10月 21

よくわからないのでとりあえず愚直なやり方で行います。数値が大量に出てくるのでいちいち約分はしていません。意外と計算が多いので間違いがあるかもしれません。

a)おもむろにテレビをつけてひとつの試合の結果を知ったケース

まず見た結果が第何試合目の結果なのかを考えます。1〜4試合目は必ず行われるが7試合目はそれまでに決着が付けば行われません。7戦目の実行の確率が下がることにより、目にした試合結果は7試合目の結果であるより1試合目の結果である確率の方が高い。このように、見た結果が第何試合目の結果なのかはその試合の行われる確率に依存する考え方をします。

1〜7試合目のそれぞれの試合が実行される確率を計算します(1〜4は当然100%です)。4戦以降のそれぞれの時点で何勝何敗が何パターンあるか確かめながら調べます。パターンとは各試合の勝ち負けの組み合わせのパターンのことです。各試合の勝ち負けの組み合わせが異なっても何勝何敗かは同じになるものがかなりあります。
以降、4-0という表記は4勝0敗を意味します。

4戦目終了時点
4-0 1パターン ここで終わり
3-1 4パターン 次へ
2-2 6パターン 次へ
1-3 4パターン 次へ
0-4 1パターン ここで終わり
よって14/16(7/8)が次へ

5戦目終了時点
4-1 4パターン ここで終わり
3-2…

Swiftのコンパイルエラー寄せ集め

Appleが2014年6月に出してきた新しいプログラミング言語Swiftのコンパイルエラーの収集。こんなプログラムでこんなエラーが出ました、という例をいくつか集めたものです(仕様を読みながらわざとエラーを出したものもかなり含む)。理想を言うならコンパイルの工程を理解した上でそれぞれの説明をしたいのだが、かなり専門的になるのでそこまでは出来ない。
(2016/12/26よりSwift 3に対応開始)

宣言、初期化の実行文
Type annotation missing in pattern 型の指定がない(型がわからない) 【確認ver】Swift 3.0.2【語】annotation 注釈

//Swift 3.0.2 var abc //エラー abcが何の型かわからない。
var abc: Int や var abc = 0 なら型が決まる(推測できる)のでOK。

//Swift 3.0.2 var a, b, c: Int = 0 //エラー Intと=0はcのみに対して適用されるようで、aとbが不確定になる。
var a, b, c: IntならOK。

//Swift 3.0.2 var a, b = 0, c: Int //エラー aに対して、= 0は適用されない(bに対して適用)、Intもaに対して適用されない(間に= 0が適用されたbがあるため?)



Cannot assign to value: '***' is a 'let' constant 値を代入できません。***はletで定義された定数です。 【確認ver】Swift 3.0.2【語】assign 割り当てる
値を初期値以外にするならvarで宣言すること。

//Swift 3.0.2 let abc = 0 abc = 1 //エラー
//Swift 3.0.2 func funcA(a: Int) { a = 0 //エラー } 関数の引数で与えられたものを関数内で変更しようとした。関数の引数はデフォルトで定数扱い。関数内で変数として使いたいなら関数の頭でvar a = aなどとして書き換え可能にする。



Cannot assign to value: '***' returns immutable value 値を代入できません。***は変更できない値です。 【確認v…