2017-03-01 4 views
3

Ich lese derzeit Chris Adamson "Learning Core Audio" und versuchen zu folgen in Swift 3 (anstelle von Objective-C).Swift 3 - Arbeiten mit UnsafePointer <CFDictionary>?

Das erste Codebeispiel macht Gebrauch von AudioTool Informationen über eine Audio-Datei zu sammeln. Meine Swift 3-Version sieht wie folgt aus:

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() 

Alles scheint groß (alle Behauptungen/AudioToolbox -API Anruf Pass) zu arbeiten. Jetzt frage ich mich, wie ich die in der outDataPointer gespeicherten Daten anzeigen kann.

Das ist, wie ich die Situation verstehe: outDataPointer hält ein optional mit zugehörigem Typ UnsafePointer<CFDictionary>. Ich bin in der Lage zu überprüfen, ob outDataPointer nicht nil daher den zugehörigen Wertes Zugriff nicht mein Programm zum Absturz bringen. outDataPointer!.pointee soll mir gibt die CFDictionary auf dem durch den zugehörigen Wert hinter outDataPointer. CFDictionary ist gießbar zu NSDictionary.

Dumping Leider die darunter liegenden Daten drucken

  • __NSAtom # 0

an die Konsole. Ziemlich nicht was ich erwartet hatte (Informationen über die Audiodatei). Wie kann ich diese Daten aus meiner Variablen outDataPointer erhalten?

Antwort

5

Swift CFDictionary ist nicht selbst eine Datenstruktur; Es ist ein Zeiger auf eine Datenstruktur und entspricht Objective-C CFDictionaryRef. Mit anderen Worten, es verhält sich wie ein Swift class, nicht ein struct.

Der in outDataPointer geschriebene Wert ist kein Zeiger auf CFDictionary; es ist ein CFDictionary. Sie demeferenzieren es zu oft, wodurch die im Wörterbuch gespeicherten Daten als Zeiger auf ein Wörterbuch behandelt werden. Auf meinem System war die resultierende Speicheradresse 0x001dffffc892e2f1, die Objective-C behandelt als tagged pointer, was in der NSAtom Nachricht.

das Problem zu beheben, erklären outDataPointer als CFDictionary? anstelle eines UnsafePointer<CFDictionary>?:

// Get metadata 
var outDataPointer: CFDictionary? = nil 

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

let outData = outDataPointer! as NSDictionary 
dump(outData) 

Ausgang:

▿ 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 
+0

Vielen Dank für die ausführliche Antwort! Das hat mir definitiv die Dinge aufgeräumt. Ich bin mir nicht einmal sicher, wie ich 'UnsafePointer ' an ​​erster Stelle verwendet habe. Alles funktioniert jetzt wie erwartet. – Herickson

+0

@NobodyNada, was ist der Grund für die Verwendung von 'CFDictionary', wenn wir' NSDictionary' direkt in 'AudioFileGetProperty' verwenden können? Und gibt es eine Möglichkeit, Swift Dictionary zu verwenden? (Ich versuchte [String: Any] und es war nicht mit Schlüssel/Werten gefüllt ...) Danke –

Verwandte Themen