Swift 3 - 使用 UnsafePointer<CFDictionary>?

Swift 3 - Working with UnsafePointer<CFDictionary>?

我目前正在阅读 Chris Adamson 的 "Learning Core Audio" 并尝试阅读 Swift 3(而不是 Objective-C)。

第一个代码示例使用 AudioTool 来收集有关音频文件的信息。我的 Swift 3 版本如下所示:

import Foundation
import AudioToolbox

func main() {
    let arguments = CommandLine.arguments

    guard arguments.count > 1 else {
        print("Usage: CAMetaData /full/path/to/audiofile")
        return
    }

    // Get filepath out of cmd-arguments
    let audiofilePath = NSString(string: arguments[1]).expandingTildeInPath

    // Load audio file into appropriate data structure
    let audioURL = NSURL(fileURLWithPath: audiofilePath)
    var audiofile: AudioFileID? = nil
    var possibleError = noErr

    possibleError = AudioFileOpenURL(audioURL, AudioFilePermissions.readPermission, 0, &audiofile)
    assert(possibleError == noErr)

    // Get size of metadata dictionary
    var outDataSize: UInt32 = 0

    possibleError = AudioFileGetPropertyInfo(audiofile!, kAudioFilePropertyInfoDictionary, &outDataSize, nil)
    assert(possibleError == noErr)

    // Get metadata
    var outDataPointer: UnsafePointer<CFDictionary>? = nil

    possibleError = AudioFileGetProperty(audiofile!, kAudioFilePropertyInfoDictionary, &outDataSize, &outDataPointer)
    assert(possibleError == noErr)

    // How to use this outDataPointer?
    let outData = outDataPointer!.pointee as NSDictionary
    dump(outData)

    // No CFRelease necessary - Swift takes care of that

    // Close connection to audiofile
    possibleError = AudioFileClose(audiofile!)
    assert(possibleError == noErr)
}

main()

一切似乎都很好(所有断言/AudioToolbox-API 调用通过)。现在我问自己如何显示 outDataPointer 中存储的数据。

我是这样理解这种情况的:outDataPointer 持有一个关联类型 UnsafePointer<CFDictionary> 的可选值。我能够验证 outDataPointer 不是 nil,因此访问关联值不会使我的程序崩溃。 outDataPointer!.pointee 应该给我 outDataPointer 后面的关联值指向的 CFDictionaryCFDictionary 可转换为 NSDictionary

可悲地丢弃底层数据打印

  • __NSAtom #0

到控制台。完全不是我所期望的(关于音频文件的信息)。如何从我的 outDataPointer 变量中获取这些数据?

Swift 的 CFDictionary 本身不是数据结构;它是一个指向数据结构的指针,相当于Objective-C的CFDictionaryRef。换句话说,它的行为类似于 Swift class,而不是 struct

写入outDataPointer的值不是指向CFDictionary的指针;它一个CFDictionary。您取消引用它的次数太多,导致存储在字典中的数据被视为指向字典的指针。在我的系统上,生成的内存地址是 0x001dffffc892e2f1,Objective-C 将其视为 tagged pointer,导致 NSAtom 消息。

要解决此问题,请将 outDataPointer 声明为 CFDictionary? 而不是 UnsafePointer<CFDictionary>?

// Get metadata
var outDataPointer: CFDictionary? = nil

possibleError = AudioFileGetProperty(audiofile!, kAudioFilePropertyInfoDictionary, &outDataSize, &outDataPointer)
assert(possibleError == noErr)

let outData = outDataPointer! as NSDictionary
dump(outData)

输出:

▿ 1 key/value pair #0
  ▿ (2 elements)
    - .0: approximate duration in seconds #1
      - super: __NSCFString
        - super: NSMutableString
          - super: NSString
            - super: NSObject
    - .1: 187.387 #2
      - super: NSString
        - super: NSObject