引数に配列とポインタを持つ関数を扱う

わたくし個人の好みでありますが、関数の引数に配列やポインタを指定し、そこにデータを仕込むという方法をよく使います。

戻り値として配列やポインタを返す方法もありますが、関数の戻り値はその関数が成功したか失敗したか、という情報を知らせることに使いたい気持ちが大きいです。

というわけで、関数の引数に配列やポインタを指定する方法を紹介します。

配列を引数にもつ関数の定義

いわゆる引数の参照渡しです。C言語などをやったことがある人は、配列なのに inout というキーワードが必要なことに違和感がありますね。まあ、こういうものだと思うしかないです。

    func SetValueToArray( _ data: inout [Double] ) -> Bool {

        for n in 0 ..< data.count {
            data[n] = Double(n) * 0.1
        }

        return true

    }

ポインタを引数にもつ関数の定義

こちらは、UnsafeMutablePointer を引数にとるタイプの関数です。こちらの場合はC言語っぽくコールすることができ、参照渡し(アドレス渡し)となります。後述する実際のコードを見ればそれがわかります。

    func SetValueToPointer( _ data: UnsafeMutablePointer<Double>, _ num_alloc: Int ) -> Bool {

        if num_alloc <= 0 {
            return false
        }

        for n in 0 ..< num_alloc {
            data[n] = Double(n) * 0.01
        }

        return true

    }

実際のコード

冒頭の10、11行目で、配列の宣言と、ポインタの宣言をしていますが、領域の確保はしていません。

VStack が表示されたとき、つまり onAppear のときに、配列を確保してデータを仕込む関数をコールします。同様にポインタの指すメモリ領域を確保してデータを仕込む関数をコールします。

それぞれの領域にデータを書き込んだら、それを Text に表示します。画面の上側に表示されるのが配列に格納された値です。画面の下側に表示されるのがポインタの指すメモリに格納された値です。

import SwiftUI

struct ContentView: View {

    @State var TheStr000: String = ""
    @State var TheStr100: String = ""

    let NUM_ALLOC = 8

    @State var Data000 = [Double]()
    @State var Data100: UnsafeMutablePointer<Double>?

    var body: some View {

        VStack {

            Spacer()

            // 配列に格納された値を表示する.
            Text( TheStr000 )

            Spacer()

            // ポインタが指すメモリに格納された値を表示する.
            Text( TheStr100 )

            Spacer()

        }.onAppear{

            // -----------------------------------------------------
            // 配列

            // 配列を確保する.
            Data000 = Array( repeating: 0.0, count: NUM_ALLOC )

            // 配列にデータを仕込む.
            let _ = SetValueToArray( &Data000 )

            // Text に表示する文字列.
            for n in 0 ..< Data000.count {
                TheStr000 += String( format: "%.3f\n", Data000[n] )
            }

            // -----------------------------------------------------


            // -----------------------------------------------------
            // ポインタ

            // メモリ領域を確保する.
            Data100 = UnsafeMutablePointer<Double>.allocate( capacity: NUM_ALLOC )

            // ポインタが指すメモリ領域にデータを仕込む.
            let _ = SetValueToPointer( Data100!, NUM_ALLOC )

            // Text に表示する文字列.
            for n in 0 ..< NUM_ALLOC {
                TheStr100 += String( format: "%.3f\n", Data100![n] )
            }

            // メモリ領域を破棄する.
            Data100!.deallocate()

            // -----------------------------------------------------

        }

    }

    // 引数に配列を与えて、そこにデータを入れる.
    func SetValueToArray( _ data: inout [Double] ) -> Bool {

        for n in 0 ..< data.count {
            data[n] = Double(n) * 0.1
        }

        return true

    }

    // 引数にポインタを与えて、そこにデータを入れる.
    func SetValueToPointer( _ data: UnsafeMutablePointer<Double>, _ num_alloc: Int ) -> Bool {

        if num_alloc <= 0 {
            return false
        }

        for n in 0 ..< num_alloc {
            data[n] = Double(n) * 0.01
        }

        return true

    }

}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}