我已经有一个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非常简单(在大多数情况下不需要模拟(
- 保留周期的问题较小,在大多数情况下,您不需要弱属性
- 避免零,零和选项(他们污染您的代码(
- ...