如何复制对象,如AVAudioPlayer

时间:2009-07-25 07:41:40

标签: iphone objective-c cocoa-touch

我很惊讶很少有对象实现NSCopying。这是我需要复制现有对象的两周内第三次,无需转到磁盘并重新加载,或重新创建对象并设置其设置。

现在我必须复制一个AVAudioPlayer声音。为什么?我想播放声音两次,没有sound.currentTime决定第二次播放的播放位置。

我认为做一个类或子类AVAudioPlayer并实现copyWithZone可能很容易。但是,AVAudioPlayer的内部是隐藏的,我不能轻易复制它们。

我现在渴望好旧的BlockMove(& var,& newVar,sizeof(varType));

如何最好地复制AVAudioPlayer声音或UIView视图?

2 个答案:

答案 0 :(得分:3)

许多对象不支持NSCopying的原因是因为它并不总是清楚复制对象应该是什么,特别是“复制对象”意味着什么的过分迂腐细节。

在这种情况下,我会采取务实的态度。如果您需要一次AVAudioPlayer重复的实例,我建议您:

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

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

这并不是一般解决方案,因为它不能处理所有情况。这是一个例子,说明如何在依赖某些特定于用法的不变量时解决问题。如果audioPlayer未使用NSData对象进行初始化,而是使用url进行初始化,则会导致此中断的最显着示例。它还对data的可变性做出了一些相对安全的假设,以及AVAudioPlayer如何编码来处理这些情况。 (我没有长时间查看文档,看看是否记录了这种极端情况行为。)

如果您需要做很多事情,可以将实现NSCopying的更复杂的代码混合在一起。由于文档的快速传递仅通过init或通过NSData两种方式url对象,并且要复制的实例化对象提供了该信息...然后,非最佳deep copy NSCopying子类的实现留给读者练习。 :)

答案 1 :(得分:0)

我看到了一个Apple示例文件CASound.mm,它有一个-copyWithZone:

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

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

查看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;
    }
}

现在,我不知道Apple是否喜欢乱搞像_impl这样的私人领域,但这基本上归结为从文件中重新获得AVPlayer,而不仅仅是现有声音的记忆副本。

我实际上希望NSCopyObject可能会做这件事,但我看到Apple并不依赖它来制作整个副本。