2009-07-25 49 views
0

我很驚訝於很少有對象實現NSCopying。這是兩週內第三次需要複製現有對象,而不必轉到磁盤並重新加載,或重新創建對象並設置其設置。如何複製對象,就像AVAudioPlayer

現在我必須複製AVAudioPlayer聲音。爲什麼?我想要兩次播放聲音,而不是使用sound.currentTime來確定第二個播放的播放位置。

我認爲這可能很容易做一個類或AVAudioPlayer的子類和實現copyWithZone。然而,AVAudioPlayer的內部是隱藏的,我不能輕易複製它們。

我現在嚮往好的老BlockMove(& var,& newVar,sizeof(varType));

如何最好地複製AVAudioPlayer聲音或UIView視圖?

回答

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。由於在文檔上的快速傳遞只能通過兩種方式到達對象,通過NSData或通過url,並且要被複制的實例化對象提供該信息...則非實現非最佳子類是留給讀者作爲練習。 :)

+0

這沒有奏效,因爲我的AVAudioPlayer來自文件URL。看一些底層的Core Audio代碼示例,我發現Apple以不同的方式實現了複製功能,這實際上並不是我正在尋找的。看到我的「答案」,因爲我在評論部分的空間有限。 – mahboudz 2009-07-27 07:42:36

0

我看到一個蘋果樣本文件,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; 
    } 
} 

現在,我不知道,如果蘋果喜歡我們搞亂_impl這樣的私人領域,但這基本上歸結爲與從文件中重新獲得AVPlayer一樣的東西,而不僅僅是製作現有聲音的內存副本。

我當時真的希望NSCopyObject能夠做到這一點,但我看到蘋果公司並沒有依賴它來做整個副本。