将Swift中的属性绑定到NSTextFields

时间:2016-02-23 02:50:34

标签: swift cocoa cocoa-bindings nstextfield

我正在研究用Swift编写的单位转换器,它会在适当的NSTextField s内自动显示更新的单位。对于此示例,如果用户在minutesField中输入分钟,则secondsFieldhoursField应自动更新以显示属性中的转换值。下面是我的视图控制器中的代码示例:

import Cocoa

class ViewController: NSViewController {

    @IBOutlet weak var secondsField: NSTextField!
    @IBOutlet weak var minutesField: NSTextField!
    @IBOutlet weak var hoursField: NSTextField!

    var sec: Double = 1
    var min: Double = 1
    var hr: Double = 1

    let conv = [[1,     0.0166666666666667, 0.000277777777777778],
                [60,    1,                  0.0166666666666667],
                [3600,  60,                 1]]

    func updateTextFields() {
        secondsField.stringValue = "\(sec)"
        minutesField.stringValue = "\(min)"
        hoursField.stringValue = "\(hr)"
    }
}

extension ViewController: NSTextFieldDelegate {

    override func controlTextDidChange(obj: NSNotification) {

        let tag = obj.object?.tag() ?? 0
        let text = obj.object?.stringValue ?? "1"
        let value = Double(text) ?? 1.0

        switch tag {
        case 0:
            // base unit = seconds
            sec = value
            min = value * conv[0][1]
            hr = value * conv[0][2]
        case 1:
            // base unit = minutes
            sec = value * conv[1][0]
            min = value
            hr = value * conv[1][2]
        case 2:
            // base unit = hours
            sec = value * conv[2][0]
            min = value * conv[2][1]
            hr = value
        default:
            "none"
        }
        updateTextFields()
    }    
}

上面的代码更新了文本字段,但是第一个按键后输入冻结的活动字段。例如,如果您尝试在秒字段中输入60,则下一个键击不会执行任何操作。第一个击键后出现数字6.0(见下图)。这可能是由于在更新属性后调用的函数。根据活动文本字段的标记更新属性。

是否可以使用一个函数来更新当前活动字段以外的所有其他文本字段?

enter image description here

2 个答案:

答案 0 :(得分:0)

您需要移动文本字段的设置' seconds之外的值到单独的方法。从secondsField.floatValue以及{{1}}属性上的{{1}}属性观察者调用该方法。

您还需要为更改秒,分钟或小时字段时创建操作方法。在秒字段的操作方法中,将{{1}}属性设置为{{1}}。对于其他两个领域也是如此。在NIB /故事板中,连接文本字段'对视图控制器上相应操作方法的操作。

答案 1 :(得分:0)

  

是否可以使用更新所有其他文本的功能   当前活动字段以外的字段?

是。您可以将所有文本字段连接到同一操作。

首先将所有文本字段相应地连接到视图控制器:

@IBOutlet weak var hourField: NSTextField!
@IBOutlet weak var minuteField: NSTextField!
@IBOutlet weak var secondField: NSTextField!

第二次创建一个var来表示您的时间间隔。您还可以添加setter / getter以将其自动存储到USerDefaults:

var timeInterval: TimeInterval {
    get {
        return UserDefaults.standard.double(forKey: "timeInterval")
    }
    set {
        UserDefaults.standard.set(newValue, forKey: "timeInterval")
    }
}

第三步创建一个TimeInterval扩展名,将时间从秒转换为小时/分钟

extension TimeInterval {
    var second: Double { return self }
    var minute: Double { return self / 60 }
    var hour:   Double { return self / 3600 }
    var hourToMinute:   Double { return self * 60 }
    var hourToSecond:   Double { return self * 3600 }
    var minuteToHour:   Double { return self / 60 }
    var minuteToSecond: Double { return self * 60 }
}

第四步创建将更新其他文本字段的操作:

@IBAction func timeAction(sender: NSTextField) {
    // use guard to convert the field string to Double
    guard let time = Double(sender.stringValue) else { return }
    // switch the field  
    switch sender {
    case hourField:
        // convert / update secondary fields
        minuteField.stringValue = time.hourToMinute.description
        secondField.stringValue = time.hourToSecond.description
        // make it persist through launches
        timeInterval = time * 3600
    case minuteField:
        hourField.stringValue = time.minuteToHour.description
        secondField.stringValue = time.minuteToSecond.description
        timeInterval = time * 60
    default:
        hourField.stringValue = time.hour.description
        minuteField.stringValue = time.minute.description
        timeInterval = time
    }
}

最后但并非最不重要的是确保您下次出现视图时加载值:

override func viewWillAppear() {
    hourField.stringValue = timeInterval.hour.description
    minuteField.stringValue = timeInterval.minute.description
    secondField.stringValue = timeInterval.second.description
}

Sample Project