亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

通過可選綁定在Swift中進行安全(邊界檢查)數組查找?

通過可選綁定在Swift中進行安全(邊界檢查)數組查找?

慕婉清6462132 2019-08-09 15:45:41
通過可選綁定在Swift中進行安全(邊界檢查)數組查找?如果我在Swift中有一個數組,并嘗試訪問超出范圍的索引,則會出現一個不足為奇的運行時錯誤:var str = ["Apple", "Banana", "Coconut"]str[0] // "Apple"str[3] // EXC_BAD_INSTRUCTION但是,我會想到Swift帶來的所有可選鏈接和安全性,這樣做會很簡單:let theIndex = 3if let nonexistent = str[theIndex] { // Bounds check + Lookup    print(nonexistent)     ...do other things with nonexistent...}代替:let theIndex = 3if (theIndex < str.count) {         // Bounds check    let nonexistent = str[theIndex] // Lookup    print(nonexistent)        ...do other things with nonexistent... }但事實并非如此 - 我必須使用ol' if語句來檢查并確保索引小于str.count。我嘗試添加自己的subscript()實現,但我不知道如何將調用傳遞給原始實現,或者不使用下標符號來訪問項目(基于索引):extension Array {     subscript(var index: Int) -> AnyObject? {         if index >= self.count {             NSLog("Womp!")             return nil         }         return ... // What?    }}
查看完整描述

3 回答

?
莫回無

TA貢獻1865條經驗 獲得超7個贊

我偶然發現了一種更好的實現此功能的方法:

Swift 3.2和更新版本

extension Collection {

    /// Returns the element at the specified index if it is within bounds, otherwise nil.    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }}

Swift 3.0和3.1

extension Collection where Indices.Iterator.Element == Index {

    /// Returns the element at the specified index if it is within bounds, otherwise nil.    subscript (safe index: Index) -> Generator.Element? {
        return indices.contains(index) ? self[index] : nil
    }}

斯威夫特2

extension CollectionType {

    /// Returns the element at the specified index if it is within bounds, otherwise nil.    subscript (safe index: Index) -> Generator.Element? {
        return indices.contains(index) ? self[index] : nil
    }}

let array = [1, 2, 3]for index in -20...20 {
    if let item = array[safe: index] {
        print(item)
    }}


查看完整回答
反對 回復 2019-08-09
?
慕少森

TA貢獻2019條經驗 獲得超9個贊

如果你真的想要這種行為,它就像你想要一個Dictionary而不是一個數組。字典nil在訪問丟失的密鑰時返回,這是有道理的,因為要知道密鑰是否存在于字典中要困難得多,因為這些密鑰可以是任何東西,在數組中密鑰必須在以下范圍內:0to count。迭代這個范圍是非常常見的,你可以絕對肯定在循環的每次迭代中都有一個真正的值。

我認為它不能以這種方式工作的原因是Swift開發人員做出的設計選擇。舉個例子:

var fruits: [String] = ["Apple", "Banana", "Coconut"]var str: String = "I ate a \( fruits[0] )"

如果您已經知道索引存在,就像在大多數使用數組的情況下一樣,這段代碼很棒。但是,如果訪問標可能可能返回nil,那么你已經改變了返回類型Arraysubscript方法是可選的。這會將您的代碼更改為:

var fruits: [String] = ["Apple", "Banana", "Coconut"]var str: String = "I ate a \( fruits[0]! )"//                                     ^ Added

這意味著每次迭代數組時都需要解包一個可選項,或者使用已知索引執行任何其他操作,因為很少有人可以訪問超出范圍的索引。Swift設計者在訪問越界索引時以犧牲運行時異常為代價,選擇了較少的可選解包。崩潰比nil你在某個地方沒想到的邏輯錯誤更可取。

我同意他們的觀點。因此,您將不會更改默認Array實現,因為您將破壞所有需要來自數組的非可選值的代碼。

相反,您可以子類化Array,并覆蓋subscript以返回可選項。或者,更實際地,您可以Array使用執行此操作的非下標方法進行擴展。

extension Array {

    // Safely lookup an index that might be out of bounds,    // returning nil if it does not exist    func get(index: Int) -> T? {
        if 0 <= index && index < count {
            return self[index]
        } else {
            return nil
        }
    }}var fruits: [String] = ["Apple", "Banana", "Coconut"]if let fruit = fruits.get(1) {
    print("I ate a \( fruit )")
    // I ate a Banana}if let fruit = fruits.get(3) {
    print("I ate a \( fruit )")
    // never runs, get returned nil}

Swift 3更新

func get(index: Int) ->T? 需要被替換 func get(index: Int) ->Element?


查看完整回答
反對 回復 2019-08-09
  • 3 回答
  • 0 關注
  • 676 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號