当变量更改时,更新Uilabel文本



我已经有一个Uicontrol类,需要基于UIimageView位置进行一些计算,该位置可以使用TouchEsbegan和TouchesMasged(此类中的所有内容(进行移动。我想将其显示为我以编程方式创建的uilabel。

class control : UIControl{
   ...
   let leftControl: UIImageView = UIImageView(image: UIImage(named: "left-control"))
   ...
   func leftValue() -> String{
       var leftValue : String = "0.0"
       leftValue = "(leftControl.center.x)"
       return leftValue
   }
}

和我的ViewController.swift

类ViewController:uiviewController {

let ctrl : Control = Control()
let leftLabel : UILabel = UILabel(frame: CGRect(x: 40, y: 300, width: 150, height: 30))
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    ctrl.frame.origin = CGPoint(x: 40, y: 400)
    leftLabel.text = "(ctrl.leftValue())" //displays only starting value
    view.addSubview(slider)
    view.addSubview(leftLabel)
    view.addSubview(rightLabel)
}

我知道它在ViewDidload内部,因此无法正确更新。我想知道计划中的timer,但不知道它是否很好。

您可以使用协议和委托在Control的文件中实现此目的:

protocol ControlDelegate: class {
    func controlPositionDidChange(leftValue: String)
}

并在Control类中添加weak var delegate: ControlDelegate?

在文件中以进行视图控制器进行以下更改:

class ViewController: UIViewController, ControllDelegate {
let ctrl : Control = Control() 
let leftLabel : UILabel = UILabel(frame: CGRect(x: 40, y: 300, width: 150, height: 30))
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    ctrl.frame.origin = CGPoint(x: 40, y: 400)
    ctrl.delegate = self
    leftLabel.text = "(ctrl.leftValue())" //displays only starting value
    view.addSubview(slider)
    view.addSubview(leftLabel)
    view.addSubview(rightLabel) 
}
func controlPositionDidChange(leftValue: String) {
    leftLabel.text = leftValue
}
}

现在,只要您想通知代表您的控件已更改位置,只需在适当的位置致电self.delegate?.controlPositionDidChange(self.leftValue())

通常,文档中还有更多。我强烈建议通过它们阅读,因为委托和协议被广泛用于Cocoatouch。

@losiowaty的答案描述了大多数开发人员选择的解决方案。但是(我认为(有很多更好的方法可以实现它。我更喜欢面向对象的解决方案。它可能看起来更像是更多的代码,但是使用更多可重复使用的代码,它是一种更好的维护方法。

您问题的真正面向对象的解决方案可能看起来像:

// reusable protocol set
protocol OOString: class {
    var value: String { get set }
}
// reusable functional objects
final class RuntimeString: OOString {
    init(initialValue: String = "") {
        self.value = initialValue
    }
    var value: String
}
final class ViewUpdatingString: OOString {
    init(_ decorated: OOString, view: UIView) {
        self.decorated = decorated
        self.view = view
    }
    var value: String {
        get {
            return decorated.value
        }
        set(newValue) {
            decorated.value = newValue
            view.setNeedsLayout()
        }
    }
    private let decorated: OOString
    private let view: UIView
}
// reusable ui objects
final class MyLabel : UILabel {
    init(frame: CGRect, imageXCenter: OOString) {
        self.imageXCenter = imageXCenter
        super.init(frame: frame)
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("Not supported")
    }
    override func layoutSubviews() {
        super.layoutSubviews()
        text = imageXCenter.value
    }
    private let imageXCenter: OOString
}
final class MyControl : UIControl {
    init(frame: CGRect, imageXCenter: OOString) {
        self.imageXCenter = imageXCenter
        super.init(frame: frame)
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("Not supported")
    }
    private let imageXCenter: OOString
    private let leftControl = UIImageView(image: UIImage(named: "left-control"))
    // call this at change
    private func updateValue() {
        imageXCenter.value = "(leftControl.center.x)"
    }
}
// non reusable business logic
final class MyViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let dependency = RuntimeString(initialValue: "unset")
        let leftLabel = MyLabel(
            frame: CGRect(x: 40, y: 300, width: 150, height: 30),
            imageXCenter: dependency
        )
        let control = MyControl(
            frame: CGRect(x: 40, y: 400, width: 400, height: 400),
            imageXCenter: ViewUpdatingString(dependency, view: leftLabel)
        )
        view.addSubview(leftLabel)
        view.addSubview(control)
    }
}

主要思想是将两个对象的依赖性提取到另一个对象中,然后使用装饰器,然后自动在每个设定值上更新UI。

注意:

  • 此方法遵循面向对象的编码规则(干净的编码,优雅的对象,装饰器图案,...(
  • 可重复使用的类是非常简单的构造,完全填充了一个任务
  • 课程通过协议互相交流
  • 依赖性通过依赖注入尽可能
  • 给出
  • 内部对象功能是私有的(松散耦合(
  • 所有内容(业务逻辑除外(旨在重复使用 ->如果您像这样编码,可重复使用的代码的组合随着每天的代码而增长
  • 您的应用程序的业务逻辑更集中在一个地方(在我的实际编码中,甚至在UiviewController之外(
  • 在为协议使用假实现时,可重复使用的对象的Unitesting非常简单(在大多数情况下不需要模拟(
  • 保留周期的问题较小,在大多数情况下,您不需要弱属性
  • 避免零,零和选项(他们污染您的代码(
  • ...

最新更新