2016年10月2日日曜日

Swift3.0でdo-catch構文によるエラーハンドリング

Javaなどにあるtry-catch構文のSwift版、と言ったところでしょうか。

let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
let input:AVCaptureDeviceInput?
do {
    input = try AVCaptureDeviceInput.init(device: device)
} catch  {
    input = nil
}
実行する分の手前にtryキーワードを置くところがポイント。 また、catchの部分でパターンマッチも可能で、

var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
    try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
} catch VendingMachineError.invalidSelection {
    print("Invalid Selection.")
} catch VendingMachineError.outOfStock {
    print("Out of Stock.")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
    print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.")
}
// Prints "Insufficient funds. Please insert an additional 2 coins."
なんて書き方もできる。 ちなみにエラーを投げる関数を定義する場合には、戻り値の手前にthrowsキーワードをつける必要あり。

func canThrowErrors() throws -> String
参考: The Swift Programming Language (Swift 3): Error Handling

Swift3.0でのC言語っぽいforループ

Swift3の破壊的変更が話題ですが、久々にSwiftを書くとその破壊っぷりに驚きます。 例えばforループといえば一般にC言語風forループのイメージが強いですが、

for(int i = 0; i < length; i++){
    // do something...
}
Swift3ではこの書き方ができなくなります。 代わりに、for inを使ってね、とのこと。 具体的には以下。

for i in (0..<length) {
    // do something...
}
ということで、気をつけましょう。

2016年10月1日土曜日

Swift3.0で長さの決まった配列を宣言する方法

久しぶりにXcodeをアップデートしてSwiftを触ってみると、だいぶ以前と感触が違っていて驚き。

ガンガンアップデートされてより良い言語になっているのであろうけれども、ちょっとブランクがある好きに全く違う言語になってしまうのは少々厳しいところ。とはいえ久々にiPhoneでGPGPU的なプログラムを書きたい気分なので、Swiftを使わない手はないでしょう。

ということで今詰まった固定長の配列の宣言方法について。

var fixedLengthArray = [Int](repeating: 0, count: 100)

repeatingを変えると初期の数値が変更でき、countで長さを決定。

何のためにこれをしているかというと、OpenGL ESでテクスチャを読み込むために、UIImageから生のピクセルデータを取り出す必要があったから。



let width = Int(image.size.width)
let height = Int(image.size.height)
var pixelData = [GLubyte](repeating: 0, count: width * height * 4)
let colorSpace = image.cgImage?.colorSpace
let context = CGContext.init(data: &pixelData, width: width, height: height, bitsPerComponent: 8, bytesPerRow: width * 4, space: colorSpace!, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)
context?.draw(in: CGRect(x: 0, y: 0, width: CGFloat(width), height: CGFloat(height)), image: image.cgImage!)
これでpixelDataの中に生情報が格納されたはず。 このデータをテクスチャにアップロードして、テクスチャをバインドしてレンダリングすれば絵が出るぞ!