subViewA 如何改变 subviewB 的参数?

How subViewA change the param on subviewB?

我用

创建了 two views in Main.storyboard
class ViewController: UIViewController 
{
   var cardsOnTableCounts = 0
   @IBOutlet weak var headStackView: HeadStackView!
   @IBOutlet weak var gridCardView: GridView!

   @objc func touchDeal3Card () 
   {
    gridCardView.cellCounts += 3
   }
} 

我在 class HeadStackView

中创建了一个按钮
class HeadStackView: UIView 
{
  var deal3Card: UIButton = UIButton.init()

  override func draw(_ rect: CGRect) {
    setDeal3Card()
  }

  private func setDeal3Card () {
    let leftButtonFrame : CGRect = CGRect(x: bounds.maxX/15, y: bounds.maxY/6, width: bounds.maxX/3, height: bounds.maxY*0.7)
    deal3Card = UIButton.init(frame: leftButtonFrame)
    deal3Card.backgroundColor = UIColor.purple
    deal3Card.setTitle("Deal 3 Cards", for: .normal)
    deal3Card.addTarget(self, action: #selector(ViewController.touchDeal3Card), for: .touchUpInside)
    addSubview(deal3Card)
}

在GridView.swift

class GridView: UIView 
{
  var cellCount: Int = 5 {didSet { setNeedsDisplay(); setNeedsLayout()}}

  override func layoutSubviews() {
    super.layoutSubviews()
    drawGrid() // it draws cellCount of cells
  }
}      

我的目标是当 UIButton deal3Card 被按下时,gridCardView 将在 gridCardView 上重新绘制更多卡片。

上面的代码通过了编译器并显示了按钮(deal3card)。但是当我点击按钮时,出现异常:

2018-10-23 19:52:54.283032+0200 gridTest[23636:5175258] -[gridTest.HeadStackView touchDeal3Card]: unrecognized selector sent to instance 0x7fb97180c8f0

2018-10-23 19:52:54.287469+0200 gridTest[23636:5175258] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[gridTest.HeadStackView touchDeal3Card]: unrecognized selector sent to instance 0x7fb97180c8f0'

崩溃的最直接原因是这一行:

deal3Card.addTarget(self, 
    action: #selector(ViewController.touchDeal3Card), for: .touchUpInside)

目标self错误。您想要将此消息发送到实现 touchDeal3Card 的视图控制器。但是在您的代码中,self 是按钮,而按钮不是。

根据您构建的架构,最简单的解决方案是将 self 替换为 nil。这将导致 touchDeal3Card 向上渗透响应链并到达视图控制器。


话虽如此,我认为架构本身是错误的。视图控制器应该控制视图;意见不应该控制自己。视图控制器,而不是视图,应该创建按钮。这段代码完全错误的事实很好地表明了这一点:

override func draw(_ rect: CGRect) {
    setDeal3Card()
}

这完全是对 draw 的误用,会给您带来可怕的麻烦。在 draw 你唯一应该做的就是(等待)画画。在 draw 中添加子视图是错误的。