Swift 3 - 使用UnsafePointer <cfdictionary>?

时间:2017-03-01 23:32:28

标签: ios objective-c swift swift3 core-audio

我目前正在阅读Chris Adamson&#34; Learning Core Audio&#34;并尝试按照 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应该为CFDictionary后面的相关值指出outDataPointerCFDictionary可投放到NSDictionary

遗憾地转储底层数据

  
      
  • __ NSAtom#0
  •   

到控制台。不是我所期望的(关于audiofile的信息)。如何从outDataPointer变量中获取此数据?

1 个答案:

答案 0 :(得分:4)

斯威夫特CFDictionary本身并不是一个数据结构;它是指向数据结构的指针,它等同于Objective-C&#39; s 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