2017-03-09 52 views
3

我有一個全局變量的音頻播放器。 什麼是調用構造函數「嘗試」關鍵字的位置差異

do{ 
    audioPlayer = try AVAudioPlayer(contentsOf: audioURL) 
}catch {} 

當然之前將試字變量初始化

do{ 
    try audioPlayer = AVAudioPlayer(contentsOf: audioURL) 
}catch {} 

前將試之間的區別2案件上面沒有任何編譯錯誤。 謝謝

+0

我會建議第一種情況下嘗試分配和第二次嘗試啓動。但我不確定,只是猜測。 – JuicyFruit

回答

5

沒有實際的區別。如said by the language guide(重點煤礦):

當在二元操作的左手側上的表達被標記trytry?,或try! ,該操作員適用於 整個二進制表達式。也就是說,您可以使用括號作爲運營商的應用程序的範圍明確的 。

// try applies to both function calls 
sum = try someThrowingFunction() + anotherThrowingFunction() 

// try applies to both function calls 
sum = try (someThrowingFunction() + anotherThrowingFunction()) 

// Error: try applies only to the first function call 
sum = (try someThrowingFunction()) + anotherThrowingFunction() 

就像+,分配也是一個二進制運算符。因此,當你說

do{ 
    try audioPlayer = AVAudioPlayer(contentsOf: audioURL) 
}catch {} 

try適用於表達audioPlayerAVAudioPlayer(contentsOf: audioURL)。獨行表達audioPlayer不可能這裏拋出一個錯誤 - 因此,在這種情況下try僅適用於呼叫AVAudioPlayerinit(contentsOf:),這可以拋出。

此推導of the grammar是:

//   "try"   "audioPlayer"  "= AVAudioPlayer(contentsOf: audioURL)" 
expression → try-operator­opt ­prefix-expression ­binary-expressions­opt 

prefix-expression → prefix-operator­opt ­postfix-expression 
postfix-expression → primary-expression­ 
primary-expression → identifier­ generic-argument-clause­opt 
identifier­ → // matches "audioPlayer" (I'm not going to fully derive this bit further) 

binary-expressions → binary-expression ­binary-expressions­opt 
binary-expression → assignment-operator ­try-operator­opt­ prefix-expression 
prefix-expression → prefix-operator­opt postfix-expression 
postfix-expression → initializer-expression­ // matches AVAudioPlayer(contentsOf: audioURL)

當你說

do{ 
    audioPlayer = try AVAudioPlayer(contentsOf: audioURL) 
}catch {} 

您使用的事實,賦值表達式has the grammar of

binary-expression → assignment-operator ­try-operator­opt ­prefix-expression­

,你可以看,try-operator可以出現在這裏的運營商的右側,因此將適用於prefix-expression - 在這種情況下是AVAudioPlayer.init(contentsOf:)

因此,在這兩種情況下,您都會捕獲可能從AVAudioPlayer.init(contentsOf:)中引發的錯誤。第一個示例僅包含從操作員左側的表達式中拋出錯誤的可能性,它不可能不可能所做的。

使用您感覺更舒適的方式 - 我的個人偏好,以及與try在語言其他地方的位置更一致的選項是將try置於右側。

+3

很好的解釋。那些來自具有例外的語言的人可能會認爲'try'具有一些深刻的意義,標記longjmp的去向或其他「異常」實現細節。記住Swift異常只是'return'的一個奇特版本是有用的。 'try'對編譯器或代碼生成沒有影響。它純粹是爲了提醒程序員,這段代碼可能會拋出異常。一旦編譯器覺得'try'足夠接近提供提醒,那就很開心。 :D –

+0

其實這並不完全正確。在某些情況下,行首的'try'不會被編譯。我認爲它編譯的事實是一個錯誤。 – matt

+0

@Hamish,謝謝你的回答! – GeRyCh

2

在我看來,這編譯其實是一種錯誤的:

try audioPlayer = AVAudioPlayer(contentsOf: audioURL) 

基本上,你正在做的事情,你不應該這樣做,而你就是幸運的,它滑過在這裏編譯。考慮,作爲一個反例,如果audioPlayer正在這裏宣佈,會發生什麼:

try let audioPlayer = AVAudioPlayer(contentsOf: audioURL) // error 

編譯和修復,它正確地移動try其所屬的地方:

let audioPlayer = try AVAudioPlayer(contentsOf: audioURL) 

,我建議按照規則,因此,這是你應該使用try放置正確 - 它修改方法調用可以拋出。它有時可能作爲一個整體工作,但並非總是如此,這是一個不好的習慣。

+0

雖然這是一個稍微不同的東西 - 這是一個約束力。如果你把在看看[語法的常量聲明(https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097 -CH34-ID355),直到'='右邊的表達式纔有'try'的空間。雖然我同意這些規則是不一致的,並且在rhs上嘗試是可取的:) – Hamish

+0

@Hamish右鍵,我只是試圖灌輸「在開始時嘗試」這個概念,好的。如果我認爲它會有所幫助,我會爲此提出一個錯誤,但我知道它不會。 :) – matt

+1

'try'總是以*表達*(不是方法調用)爲前綴。這就是爲什麼前綴賦值是合法的,該賦值是'()'或'Void'類型的表達式。 'try'不需要立即在表達式的拋出部分前加上。你的例子'let audioPlayer = ...'是一個聲明,所以不能用'try'標記。 –