适用于iOS的Swift:更改数组顺序并填充Picker

时间:2015-05-02 05:22:43

标签: ios arrays swift uipickerview

我正在尝试在Swift for iOS中编写一个摄影应用程序,为指定的ƒ-停止和快门速度建立等效的曝光设置。写这个应用程序有几个下游部分我尚未到达(因此你不会看到明显组件的代码,如用户输入或快门速度)。我需要帮助的是如何根据(最终)用户定义的输入值更改数组的顺序。

我能够在Playground中成功实现这一点,但是当我尝试将它应用于ViewController.swift来填充Picker时,我遇到了问题。

这是我的Playground代码:

var setƒstop = 1.4
var ƒstopout = [Double]()

func changeRange(inout setƒstop: (Double), inout ƒstopout: [Double]) {

if setƒstop == 1.0 {
    ƒstopout = [1,1.4,2,2.8,4,5.6,8,11,16,22,32,44,64,88,128]
} else if setƒstop == 1.4 {
    ƒstopout = [1.4,2,2.8,4,5.6,8,11,16,22,32,44,64,88,128,1]
} else if setƒstop == 2.0 {
    ƒstopout = [2,2.8,4,5.6,8,11,16,22,32,44,64,88,128,1,1.4]
} else if setƒstop == 2.8 {
    ƒstopout = [2.8,4,5.6,8,11,16,22,32,44,64,88,128,1,1.4,2]
} else if setƒstop == 4.0 {
    ƒstopout = [4,5.6,8,11,16,22,32,44,64,88,128,1,1.4,2,2.8]
} else if setƒstop == 5.6 {
    ƒstopout = [5.6,8,11,16,22,32,44,64,88,128,1,1.4,2,2.8,4]
} else if setƒstop == 8.0 {
    ƒstopout = [8,11,16,22,32,44,64,88,128,1,1.4,2,2.8,4,5.6]
} else if setƒstop == 11.0 {
    ƒstopout = [11,16,22,32,44,64,88,128,1,1.4,2,2.8,4,5.6,8]
} else if setƒstop == 16.0 {
    ƒstopout = [16,22,32,44,64,88,128,1,1.4,2,2.8,4,5.6,8,11]
} else if setƒstop == 22.0 {
    ƒstopout = [22,32,44,64,88,128,1,1.4,2,2.8,4,5.6,8,11,16]
} else if setƒstop == 32.0 {
    ƒstopout = [32,44,64,88,128,1,1.4,2,2.8,4,5.6,8,11,16,22]
} else if setƒstop == 44.0 {
    ƒstopout = [44,64,88,128,1,1.4,2,2.8,4,5.6,8,11,16,22,32]
} else if setƒstop == 64.0 {
    ƒstopout = [64,88,128,1,1.4,2,2.8,4,5.6,8,11,16,22,32,44]
} else if setƒstop == 88.0 {
    ƒstopout = [88,128,1,1.4,2,2.8,4,5.6,8,11,16,22,32,44,64]
} else if setƒstop == 128.0 {
    ƒstopout = [128,1,1.4,2,2.8,4,5.6,8,11,16,22,32,44,64,88]
}
}

changeOrder(&setƒstop, &ƒstopout)


println(ƒstopout)
println(ƒstopout[0])

这是我的ViewController.swift代码:

import UIKit

var setƒstop = 1.4
var ƒstopout = [Double]()

func changeRange(inout setƒstop: (Double), inout ƒstopout: [Double]) {

if setƒstop == 1.0 {
    ƒstopout = [1,1.4,2,2.8,4,5.6,8,11,16,22,32,44,64,88,128]
} else if setƒstop == 1.4 {
    ƒstopout = [1.4,2,2.8,4,5.6,8,11,16,22,32,44,64,88,128,1]
} else if setƒstop == 2.0 {
    ƒstopout = [2,2.8,4,5.6,8,11,16,22,32,44,64,88,128,1,1.4]
} else if setƒstop == 2.8 {
    ƒstopout = [2.8,4,5.6,8,11,16,22,32,44,64,88,128,1,1.4,2]
} else if setƒstop == 4.0 {
    ƒstopout = [4,5.6,8,11,16,22,32,44,64,88,128,1,1.4,2,2.8]
} else if setƒstop == 5.6 {
    ƒstopout = [5.6,8,11,16,22,32,44,64,88,128,1,1.4,2,2.8,4]
} else if setƒstop == 8.0 {
    ƒstopout = [8,11,16,22,32,44,64,88,128,1,1.4,2,2.8,4,5.6]
} else if setƒstop == 11.0 {
    ƒstopout = [11,16,22,32,44,64,88,128,1,1.4,2,2.8,4,5.6,8]
} else if setƒstop == 16.0 {
    ƒstopout = [16,22,32,44,64,88,128,1,1.4,2,2.8,4,5.6,8,11]
} else if setƒstop == 22.0 {
    ƒstopout = [22,32,44,64,88,128,1,1.4,2,2.8,4,5.6,8,11,16]
} else if setƒstop == 32.0 {
    ƒstopout = [32,44,64,88,128,1,1.4,2,2.8,4,5.6,8,11,16,22]
} else if setƒstop == 44.0 {
    ƒstopout = [44,64,88,128,1,1.4,2,2.8,4,5.6,8,11,16,22,32]
} else if setƒstop == 64.0 {
    ƒstopout = [64,88,128,1,1.4,2,2.8,4,5.6,8,11,16,22,32,44]
} else if setƒstop == 88.0 {
    ƒstopout = [88,128,1,1.4,2,2.8,4,5.6,8,11,16,22,32,44,64]
} else if setƒstop == 128.0 {
    ƒstopout = [128,1,1.4,2,2.8,4,5.6,8,11,16,22,32,44,64,88]
}
}


class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {

override func viewDidLoad() {
    super.viewDidLoad()
    changeRange(&setƒstop, &ƒstopout)
}

var arrayƒstop = ["\(ƒstopout[0])","\(ƒstopout[1])","\(ƒstopout[2])"] // etc. A truncated array is being used here for testing purposes.

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
    return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return arrayƒstop.count
}

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
    return arrayƒstop[row]
}
}

我已经尝试了几种变体,但这是我唯一没有遇到编译错误的版本。相反,当我尝试运行模拟器时,它会因错误而崩溃:

fatal error: Array index out of range
(lldb)

意味着var arrayƒstop并未使用ƒstopout的{​​{1}}值填充,而是引用func changeRange

请协助。

3 个答案:

答案 0 :(得分:1)

不要使用固定数字指定arrayƒstop,而是尝试使用for-loop或:

let arrayƒstop = ƒstopout.map { String(stringInterpolationSegment: $0) }

因为您要将Double转换为String,所以您需要为其指定一种格式:String(format: "%.1f", $0)或使用stringInterpolationSegment,如图所示在示例中。

答案 1 :(得分:1)

如果我可以提出建议:

extension Array {
    func rotated(steps : Int) -> [T] {
        return [T]( self[steps..<self.count] + self[0..<steps] )
    }
}

func indexOf<T: Equatable>(ary : [T], theItem : T) -> Int? {
    for (i, obj) in enumerate(ary) {
        if obj == theItem {
            return i
        }
    }
    return nil
}


let ƒstops = [1,1.4,2,2.8,4,5.6,8,11,16,22,32,44,64,88,128]

let ƒstopout = ƒstops.rotated( indexOf(ƒstops, setƒstop) ?? 0 )

这将消除你极度危险和容易出错的条件,如果那么thunka-thunkas。

然后在您的视图中,您执行以下操作:

var arrayƒstop = ƒstopout.map { "\($0)" }

一般来说,你永远不应该硬编码数组索引。

答案 2 :(得分:0)

您的ƒstopout数组为空,这就是导致此崩溃的原因。 您应该在调用arrayƒstop方法之后初始化changeRange,而您似乎在那里初始化其数据。

之后只需重新加载pickerView的数据。

为了确定我的意思,请在以这种方式声明时初始化ƒstopout,例如:

var ƒstopout = [1,1.4,2,2.8,4,5.6,8,11,16,22,32,44,64,88,128]

你不会有崩溃。