2016-04-11 13 views
1

機能的なプログラミングスタイルを使って辞書を構築したいと思います。私は(減らす)動作するようには思えない - 私が得る「致命的なエラー:オプションの値をアンラップしながら、予想外にnilを見つけ、」Swiftでreduce()を使って辞書を構築する

func loadMoveToCalendarsRules(calendarIndex: Int) -> [String]? { 
// return something like ["phone call", "buzz", "ring"] 
    return NSUserDefaults.standardUserDefaults().objectForKey(generateMoveToCalendarsRules_NSUserDefaultsKey(calendarIndex)) as? [String] 
} 

// Add indeces to an array of any type 
func addIndices<T>(toArray: [T]) -> [(index: Int, value: T)] { 
    return Array(zip(toArray.indices, toArray)) 
} 

typealias CalendarRules = [EKCalendar : [String]]? 
func buildCalendarRules(cals: [EKCalendar]) -> CalendarRules { 
    let sortedCals = cals.sort { $0.title.lowercaseString < $1.title.lowercaseString } 

    // build move to cal rules. 
    let indexedCalList = addIndices(sortedCals) 
    // go through the sorted calendars and build a dictionary that associates each calendar with a string array. (These are keywords that apply to the given calendar.) 
    let calendarRules = indexedCalList.reduce(nil as CalendarRules) { 
     accumulator, nextValue in 
     var retVal: [EKCalendar : [String]]? = accumulator 
     // if there are values found in NSUserDefaults for this calendar index then retrieve them. 
     if let rulesForCurrentCal = loadMoveToCalendarsRules(nextValue.index) { 
      retVal![nextValue.value] = rulesForCurrentCal  // fatal error: unexpectedly found nil while unwrapping an Optional value 
     } 
     return retVal 
    } 

    print("------------ built calendar rules -------------") 
    print(Array(arrayLiteral: calendarRules?.keys)) 
    print(Array(arrayLiteral: calendarRules?.values)) 

    return calendarRules 
} 

答えて

1

あなたretValは任意であり、そしてnilあなたが合格(初期値として開始します)、それでも強制的に展開するにはretVal!を使用しています。 [:](空の辞書)を初期値として使用することができ、retValはオプションである必要はありません。

1

nilで始まり、ディクショナリをインスタンス化しないため、!で強制アンラップを実行しようとすると失敗します。代わりに、それがnilかどうかを調べ、もしそうなら、それをインスタンス化してください。

これまでは、カレンダールールを非オプションタイプとして定義することをお勧めします。それは、物事はそれほど混乱このようになります:

typealias CalendarRules = [EKCalendar : [String]] 

次に、あなたが必要なときCalendarRulesオブジェクトをインスタンス化するために、nil -coalescing演算子、??を使用することができます。

let calendarRules = indexedCalList.reduce(nil as CalendarRules?) { accumulator, nextValue in 
    if let rulesForCurrentCal = loadMoveToCalendarsRules(nextValue.index) { 
     var retVal = accumulator ?? CalendarRules() 
     retVal[nextValue.value] = rulesForCurrentCal 
     return retVal 
    } 
    return accumulator 
} 

それはもっとあるかもしれないことを私を打ちます効率的なアプローチですが、これは "予期せぬ発見なし"というエラーに対処する必要があります。

関連する問題