【问题标题】:Swift 3 - Working with UnsafePointer<CFDictionary>?Swift 3 - 使用 UnsafePointer<CFDictionary>?
【发布时间】:2017-03-01 23:32:28
【问题描述】:

我目前正在阅读 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&lt;CFDictionary&gt; 关联类型的可选。我能够验证outDataPointer 不是nil,因此访问关联的值不会使我的程序崩溃。 outDataPointer!.pointee 应该给我CFDictionary 所指向的outDataPointer 后面的关联值。 CFDictionary 可转换为 NSDictionary

遗憾地转储底层数据打印

  • __NSAtom #0

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

【问题讨论】:

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


    【解决方案1】:

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

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

    要解决此问题,请将outDataPointer 声明为CFDictionary? 而不是UnsafePointer&lt;CFDictionary&gt;?

    // 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
    

    【讨论】:

    • 感谢您的详细解答!这无疑为我解决了问题。我什至不确定我最初是如何使用UnsafePointer&lt;CFDictionary&gt; 的。现在一切正常。
    • @NobodyNada,如果我们可以在AudioFileGetProperty 中使用NSDictionary,那么使用CFDictionary 的原因是什么?有没有办法使用 Swift Dictionary? (我试过 [String:Any] 并没有填充键/值...)谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多