Sono nuovo di swift e ho qualche difficoltà a gestire i puntatori di CFString (o NSString) non gestito. Sto lavorando su un progetto CoreMIDI che implica l'utilizzo di UnsafeMutablePointer> come si può vedere in questa funzione:?Swift UnsafeMutablePointer <Unmanaged ?> Allocazione e stampa
func MIDIObjectGetStringProperty(_ obj: MIDIObjectRef,
_ propertyID: CFString!,
_ str: UnsafeMutablePointer<Unmanaged<CFString>?>) -> OSStatus
Il mio problema è che voglio per allocare un buffer per ricevere il contenuto della proprietà (_str) quindi chiama la funzione sopra e infine stampa il contenuto nella console utilizzando println.
Al momento ho scritto questo:
// Get the first midi source (I know it exists)
var midiEndPoint : Unmanaged<MIDIEndpointRef> = MIDIGetSource(0)
//C reate a "constant" of 256
let buf = NSMutableData(capacity: 256)
// Allocate a string buffer of 256 characters (I'm not even sure this does what I want)
var name = UnsafeMutablePointer<Unmanaged<CFString>?>(buf!.bytes)
// Call the function to fill the string buffer with the display name of the midi device
var err : OSStatus = MIDIObjectGetStringProperty(&midiEndPoint,kMIDIPropertyDisplayName,name)
// Print the string ... here no surprises I don't know what to write to print the content of the pointer, so it prints the address for the moment
println(name)
non ho trovato alcun codice di esempio per utilizzare le funzioni CoreMIDI sulla mela developper libreria non su internet. Sono davvero confuso perché vengo da cpp e le cose sono molto diverse in swift.
EDIT:
Dopo le risposte Rintaro e Martin ho ancora un problema, tutta la mia prova sono fatto su iOS 8.1 e se copio il codice è portato a me il compilatore mi dice che non posso scrivere:
let err = MIDIObjectGetStringProperty(midiEndPoint, kMIDIPropertyDisplayName, &property)
I risultati in "Non gestito" non sono convertibili in "MIDIObjectRef". Quindi ho aggiunto un "&" perché MIDIObjectRef è un UnsafeMutablePointer <vuoto>.
let midiEndPoint = MIDIGetSource(0)
var property : Unmanaged<CFString>?
let err = MIDIObjectGetStringProperty(&midiEndPoint, kMIDIPropertyDisplayName, &property)
Ora: 'No gestito <MIDIEndpoint>' non è convertibile in '@lvalue inout $ T2'. Alla fine ho dovuto cambiare il primo let in var, senza capire perché?!?
var midiEndPoint = MIDIGetSource(0)
var property : Unmanaged<CFString>?
let err = MIDIObjectGetStringProperty(&midiEndPoint, kMIDIPropertyDisplayName, &property)
Il codice ora viene compilato ed eseguito, ma MIDIObjectGetStringProperty torna OSStatus sbagliare -50 che corrisponde alla IOW o da MacErros.h:
paramErr = -50, /*error in user parameter list*/
Così sembra che i parametri non sono quelli che MIDIObjectGetStringProperty è aspettando.
La fonte "0" non esiste sul mio iPad perché MIDIGetNumberOfSources() restituisce 1. Ecco il codice completo:
var numDestinations: ItemCount = MIDIGetNumberOfDestinations()
println("MIDI Destinations : " + String(numDestinations))
for var i : ItemCount = 0 ; i < numDestinations; ++i{
var midiEndPoint = MIDIGetDestination(i)
var property : Unmanaged<CFString>?
let err = MIDIObjectGetStringProperty(&midiEndPoint, kMIDIPropertyDisplayName, &property)
if err == noErr {
let displayName = property!.takeRetainedValue() as String
println(displayName)
}else{
println("error : "+String(err))
}
}
Displays:
MIDI Destinations : 1
error : -50
davvero non capisco niente. ..
UPDATE:
Infine Martin trovato la soluzione, sembra che ci siano due diverse definizioni di MIDIObjectRef in architetture a 32 e 64 bit. Mentre eseguo il codice su un vecchio iPad 2, il mio codice ha cercato di compilare in modalità 32 bit in cui il valore restituito da MIDIGetSource (i) non è convertibile in MIDIObjectRef. La soluzione è quella di "getto pericoloso" il punto finale MIDI su 32 bit architetture:
#if arch(arm64) || arch(x86_64)
let midiEndPoint = MIDIGetDestination(i)
#else
let midiEndPoint = unsafeBitCast(MIDIGetDestination(i), MIDIObjectRef.self)
#endif
... O acquistare un nuovo dispositivo a 64 bit ...
Grazie per il prezioso aiuto
mi ha confermato che questo funziona, ma penso che dovremmo usare 'takeRetainedValue() ', perché in questo caso, abbiamo la responsabilità di rilasciare' CFString' restituito. – rintaro
@rintaro: "MIDIObjectGetStringProperty" non ha "Crea" o "Copia" nel nome. Secondo le regole di gestione della memoria del Core Foundation, ciò significa che il chiamante non è responsabile del rilascio della memoria. Vedi https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html. Penso che la "regola Get" si applica qui. –
Ma, in effetti, ho confermato le perdite. vedi: https://developer.apple.com/library/mac/qa/qa1374/_index.html – rintaro