2017-04-26 95 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)
  • 單元測試可重複使用的對象使用假冒實現時的協議(甚至嘲諷不需要在大多數情況下)
  • 較小的問題,保留週期是很簡單的,在大多數情況下,你不需要弱性質的任何更
  • 避免零,零和選配(它們污染你的代碼)
  • ...
相關問題