Swift 3 - 使用 UnsafePointer<CFDictionary>?

Posted

技术标签:

【中文标题】Swift 3 - 使用 UnsafePointer<CFDictionary>?【英文标题】:Swift 3 - Working with 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 变量中获取这些数据?

【问题讨论】:

【参考方案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] 并没有填充键/值...)谢谢

以上是关于Swift 3 - 使用 UnsafePointer<CFDictionary>?的主要内容,如果未能解决你的问题,请参考以下文章

“当前 SwiftyJSON(通过 Swift 3.0.2)无法使用 Swift 3.1 导入”的原因是啥

使用 Swift 2.3 编译的模块无法在 Swift 3.0 中导入

使用 Swift 3.0.1 编译的模块无法在 BuddyBuild 上的 Swift 3.0 中导入

Cocoapods - 使用 Swift 3.0 编译的模块无法在 Swift 3.0.1 中导入

使用 Swift 4.0 编译的模块无法在 Swift 3.1 中导入框架二进制文件

如何使用 Swift 2.3 和 3.0 编译模块?