1

ここのAppleのコード例の1つで提供されているObjective Cコードを変換しようとしています: https://developer.apple.com/library/mac/samplecode/avsubtitleswriterOSX/Listings/avsubtitleswriter_SubtitlesTextReader_m.html

これまでに私が思いついた結果は次のとおりです。

func copySampleBuffer() -> CMSampleBuffer? {

    var textLength : Int = 0
    var sampleSize : Int = 0

    if (text != nil) {
        textLength = text!.characters.count
        sampleSize = text!.lengthOfBytesUsingEncoding(NSUTF16StringEncoding)
    }

    var sampleData = [UInt8]()

    // Append text length
    sampleData.append(UInt16(textLength).hiByte())
    sampleData.append(UInt16(textLength).loByte())

    // Append the text
    for char in (text?.utf16)! {
        sampleData.append(char.bigEndian.hiByte())
        sampleData.append(char.bigEndian.loByte())
    }

    if (self.forced) {
        // TODO
    }

    let samplePtr = UnsafeMutablePointer<[UInt8]>.alloc(1)
    samplePtr.memory = sampleData

    var sampleTiming = CMSampleTimingInfo()
    sampleTiming.duration = self.timeRange.duration;
    sampleTiming.presentationTimeStamp = self.timeRange.start;
    sampleTiming.decodeTimeStamp = kCMTimeInvalid;

    let formatDescription = copyFormatDescription()

    let dataBufferUMP = UnsafeMutablePointer<Optional<CMBlockBuffer>>.alloc(1)

    CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, samplePtr, sampleSize, kCFAllocatorMalloc, nil, 0, sampleSize, 0, dataBufferUMP);

    let sampleBufferUMP = UnsafeMutablePointer<Optional<CMSampleBuffer>>.alloc(1)

    CMSampleBufferCreate(kCFAllocatorDefault, dataBufferUMP.memory, true, nil, nil, formatDescription, 1, 1, &sampleTiming, 1, &sampleSize, sampleBufferUMP);

    let sampleBuffer = sampleBufferUMP.memory

    sampleBufferUMP.destroy()
    sampleBufferUMP.dealloc(1)

    dataBufferUMP.destroy()
    dataBufferUMP.dealloc(1)

    samplePtr.destroy()
    //Crash if I call dealloc here
    //Error is: error for object 0x10071e400: pointer being freed was not allocated
    //samplePtr.dealloc(1)

    return sampleBuffer;
}

ここで可能かどうかはわかりませんが、可能であれば「Unsafe*」タイプを避けたいと思います。また、構造体を使用して何らかの方法でパックすることも検討しましたが、構造体の現在のサイズではなく、定義のサイズを使用する sizeof に基づいているようです。これは私が使用したであろう構造でした:

struct SubtitleAtom {
    var length : UInt16
    var text : [UInt16]
    var forced : Bool?
}

この関数に最適な Swift 2 コードに関するアドバイスをいただければ幸いです。

4

1 に答える 1

1

したがって、最初はこのパターンを使用してコーディングします

class C { deinit { print("I got deinit'd!") } }
struct S { var objectRef:AnyObject? }

func foo() {
    let ptr = UnsafeMutablePointer<S>.alloc(1)
    let o = C()
    let fancy = S(objectRef: o)
    ptr.memory = fancy
    ptr.destroy() //deinit runs here!
    ptr.dealloc(1) //don't leak memory
}
// soon or later this code should crash :-)
(1..<1000).forEach{ i in
    foo()
    print(i)
}

遊び場で試してみると、おそらくクラッシュします:-)。どうしたの?問題は、バランスの取れていない保持/解放サイクルです。安全な方法で同じことを書く方法は?解放部分を削除しました。しかし、私のスニペットでそれを実行して、結果を確認してください。コードが再びクラッシュします:-)。唯一の安全な方法は、次のスニペットでわかるように、基になる ptr のメモリを適切に初期化および初期化解除 (破棄) することです。

class C { deinit { print("I got deinit'd!") } }
struct S { var objectRef:AnyObject? }

func foo() {
    let ptr = UnsafeMutablePointer<S>.alloc(1)
    let o = C()
    let fancy = S(objectRef: o)
    ptr.initialize(fancy)
    ptr.destroy()
    ptr.dealloc(1)
}

(1..<1000).forEach{ i in
    foo()
    print(i)
}

これで、コードは期待どおりに実行され、すべての保持/解放サイクルのバランスが取れています。

于 2016-02-29T18:45:33.637 に答える