2009-07-25 6 views
0

Je suis plutôt surpris du peu d'objets implémentant NSCopying. C'est la troisième fois en deux semaines que j'ai besoin de dupliquer un objet existant, sans devoir aller sur le disque et recharger, ou recréer l'objet et définir ses paramètres.Comment copier des objets, comme AVAudioPlayer

Maintenant, je dois dupliquer un son AVAudioPlayer. Pourquoi? Je veux jouer le son deux fois, sans avoir le sound.currentTime déterminer l'emplacement de lecture de la deuxième lecture.

Je pensais qu'il pourrait être facile de faire une catégorie ou une sous-classe AVAudioPlayer et d'implémenter copyWithZone. Toutefois, les composants internes de AVAudioPlayer sont masqués et je ne peux pas les copier facilement.

Je cherche maintenant le bon vieux BlockMove (& var, & newVar, sizeof (varType));

Comment mieux dupliquer un son AVAudioPlayer ou une vue UIView?

Répondre

3

La raison pour laquelle de nombreux objets ne supportent pas NSCopying est que la définition d'un objet copié n'est pas toujours claire, et en particulier les détails trop pédants de ce que signifie «copier un objet».

Je prendrais une approche pragmatique dans ce cas. Si vous avez besoin d'une instance de AVAudioPlayer dupliqué juste une fois, je vous recommande ceci:

AVAudioPlayer *audioPlayer; // Assumed to be valid. 
AVAudioPlayer *copiedPlayer = NULL; 

copiedPlayer = [[[AVAudioPlayer allocate] initWithData:audioPlayer.data] autorelease]; 

Ce n'est pas censé être une solution générale, car il ne gère pas tous les cas. Il est destiné à être un exemple de la façon dont vous pouvez surmonter le problème tout en comptant sur certains invariants spécifiques à l'utilisation. L'exemple le plus notable dans lequel cela casse est si audioPlayer n'a pas été initialisé avec un objet NSData, mais un url à la place. Il fait également certaines hypothèses relativement sûres sur la mutabilité de data, et comment AVAudioPlayer a été codé pour gérer ces cas. (Je n'ai pas regardé la documentation assez longtemps pour voir si de tels comportements sont documentés).

Si c'est quelque chose que vous devez faire beaucoup, vous pouvez probablement lier ensemble un peu plus compliqué de code qui implémente NSCopying. Puisqu'un passage rapide à la documentation ne révèle que deux voies à l'objet, via un NSData ou via un url, et que l'objet instancié à copier fournit cette information ... alors l'implémentation d'une sous-classe non optimale deep copyNSCopying est laissé comme un exercice pour le lecteur. :)

+0

Cela n'a pas fonctionné car mon AVAudioPlayer provenait d'une URL de fichier.En regardant quelques exemples de code Core Audio sous-jacents, je vois qu'Apple a implémenté une fonction de copie d'une manière différente, ce qui n'est pas vraiment ce que je cherche non plus. Voir ma "réponse" puisque je suis limité dans l'espace ici dans la section des commentaires. – mahboudz

0

j'ai vu un exemple de fichier Apple, CASound.mm, qui a une -copyWithZone:

/* support NSCopying */ 
- (id)copyWithZone:(NSZone *)zone 
{ 
    CASound* copy = NSCopyObject(self, 0, zone); 

    copy->_impl = NULL; 
    [copy initWithSound: self]; 
    return copy; 
} 

regardant initWithSound:

- (CASound*)initWithSound:(CASound *)other 
{ 
    CASoundImpl* otherImpl = (CASoundImpl*)other->_impl; 

    if (otherImpl->_url) { 
     return [self initWithContentsOfURL: otherImpl->_url]; 
    } else if (otherImpl->_data) { 
     return [self initWithData: otherImpl->_data]; 
    } else { 
     return NULL; 
    } 
} 

Maintenant, je ne sais pas si Apple Nous aimons nous amuser avec les champs privés comme _impl, mais cela se résume à la même chose que d'obtenir à nouveau l'AVPlayer à partir du fichier, et pas seulement de faire une copie en mémoire du son existant. En fait, j'espérais que NSCopyObject ferait l'action, mais je vois qu'Apple ne compte pas dessus pour la copie entière.

Questions connexes