2017-04-26 97 views
0

我有一个UIControl类,需要根据UIImageView位置进行一些计算,这个位置可以通过touchesBegan和touchesMoved(这个类中的所有东西)来移动。 比我想显示它作为我已经编程创建的UILabel。当变量发生变化时更新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中里面,所以它不能正常更新。我想知道有关scheduledTimer,但不知道它是否是好的解决方案。

+0

关键值观察 –

+0

@AleksandrMedvedev志愿更是一个Objective-C的功能。不过,在Swift中可能并不简单。 – Losiowaty

+1

@Losiowaty,KVO不是一个简单的功能..永远:) –

回答

2

你可以做到这一点使用协议和委托 - 在文件中为您Control补充一点:

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

,并添加一个weak var delegate: ControlDelegate?Control类。

在为视图控制器文件做出以下更改:

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())在适当的地方。

通常情况下,有more in the docs.我强烈建议阅读它们,因为委托和协议在CocoaTouch中被广泛使用。

+0

dziękiza pomoc;) – codddeer123

+0

Nie ma za co :)但让我们在这里保持英语的东西;) – Losiowaty

+0

还有一个问题 - 为什么你写'协议ControlDelegate:class {}'。这是否意味着这个ControlDelegate继承自该类?目的是什么? – codddeer123

0

@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) 
    } 

} 

主要思想是提取两个对象的依赖到另一个对象,并使用一个装饰然后自动更新每一个用户界面设定值。

注:

  • 这种方法如下面向对象编码的规则(干净的编码,优雅的对象,装饰图案,...)
  • 可重复使用的类被非常简单的构造和fullfill恰好一个任务
  • 类由协议彼此通信
  • 依赖性尽可能由依赖注入给定
  • 内部对象的功能是私人(松耦合) (如果你的代码是这样的,那么可重复使用的代码组合就会随着你的代码的增长而增长)
  • 你的应用程序的商业逻辑更集中在一个地方(在我的真正的编码甚至超出E中的UIViewController)
  • 单元测试可重复使用的对象使用假冒实现时的协议(甚至嘲讽不需要在大多数情况下)
  • 较小的问题,保留周期是很简单的,在大多数情况下,你不需要弱性质的任何更
  • 避免零,零和选配(它们污染你的代码)
  • ...
相关问题