在另一个自定义 UIView 中设置/更改嵌套自定义 UIView 的变量

Posted

技术标签:

【中文标题】在另一个自定义 UIView 中设置/更改嵌套自定义 UIView 的变量【英文标题】:Setting/Changing variables of a nested custom UIView in another custom UIView 【发布时间】:2016-06-17 10:04:07 【问题描述】:

我目前遇到了嵌套在其他自定义 UIView 中的自定义 UIView 的问题,嵌套自定义 UIView 的变量无法更改,因此无法反映在视图本身中。

目前,我有 3 个自定义 UIView:

TokenView,它只覆盖了 drawRect 以创建一个带有圆形图像的视图。

@IBDesignable class TokenView: UIView 

@IBInspectable var tokenOutlineColor: UIColor = UIColor.blackColor()
@IBInspectable var tokenBackgroundColor: UIColor = UIColor.lightGrayColor()
@IBInspectable var tokenImage: UIImage!

override init(frame: CGRect)
    super.init(frame:frame)


required init?(coder aDecoder: NSCoder) 
    super.init(coder: aDecoder)


override func drawRect(rect: CGRect) 

    var context = UIGraphicsGetCurrentContext()

    var thickness: CGFloat = 3
    var path = UIBezierPath(ovalInRect: CGRect(origin: CGPointMake(thickness/2, thickness/2), size: CGSize(width: rect.width - thickness, height: rect.height - thickness)))

    CGContextSaveGState(context)
    path.addClip()

    tokenOutlineColor.setStroke()
    tokenBackgroundColor.setFill()
    path.fill()
    if let image = tokenImage 
        tokenImage.drawInRect(rect)
    
    path.stroke()

    

PersonView,它有一个 TokenView() 作为子视图,当我更改我所说的 TokenView 的变量时,它也可以按预期工作。

class PersonView: UIView 

var name: String?
var group: PersonGroup?

required init?(coder aDecoder: NSCoder)
    super.init(coder: aDecoder)
    makePersonView()


override init(frame: CGRect) 
    super.init(frame: frame)
    makePersonView()


func makePersonView()

    if name == nil 
        self.name = "Bob"
    
    if group == nil 
        self.group = PersonGroup.Good
    

    let token = TokenView()
    token.translatesAutoresizingMaskIntoConstraints = false

    switch group! 
    case .Good:
        token.tokenOutlineColor = UIColor.greenColor()
    case .Bad:
        token.tokenOutlineColor = UIColor.redColor()
    default:
        token.tokenOutlineColor = UIColor.blueColor()
    
    token.tokenImage = UIImage(named: name!)
    token.tokenBackgroundColor = UIColor.clearColor()
    token.backgroundColor = UIColor.clearColor()        
    addSubview(token)

    let label = UILabel()
    label.text = name
    label.translatesAutoresizingMaskIntoConstraints = false
    label.textAlignment = NSTextAlignment.Center
    addSubview(label)

    NSLayoutConstraint.activateConstraints([
        token.topAnchor.constraintEqualToAnchor(topAnchor),
        token.leadingAnchor.constraintEqualToAnchor(leadingAnchor),
        token.trailingAnchor.constraintEqualToAnchor(trailingAnchor),
        token.heightAnchor.constraintEqualToConstant(frame.size.height*0.70),
        token.bottomAnchor.constraintEqualToAnchor(label.topAnchor),
        label.leadingAnchor.constraintEqualToAnchor(leadingAnchor),
        label.trailingAnchor.constraintEqualToAnchor(trailingAnchor),
        label.bottomAnchor.constraintEqualToAnchor(bottomAnchor)
        ])

和DetailedPersonView 类,由此创建PersonView 实例并从那里修改其变量,这就是问题所在。其他添加的“详细信息”工作正常,只是在类中的函数中修改时嵌套的 PersonView 中的那些。

class DetailedPersonView: UIView 

var name: String = "Marley"
var group: PersonGroup = PersonGroup.Bad

var quantity: Float = 0.00
var stat: String? = "Strength"

required init?(coder aDecoder: NSCoder)
    super.init(coder: aDecoder)
    makeDetailedPersonView()



override init(frame: CGRect) 
    super.init(frame: frame)
    makeDetailedPersonView()


func makeDetailedPersonView()
    let personView = PersonView()
    personView.translatesAutoresizingMaskIntoConstraints = false
    personView.name = name
    personView.group = group
    personView.type = type
    addSubview(personView)

    let label = UILabel()
    let quantityString = String(format: quantity == floor(quantity) ? "%.0f":"%.1f", quantity)
    if unit != nil 
        label.text = quantityString + " " + stat!
     else 
        label.text = quantityString
    
    label.translatesAutoresizingMaskIntoConstraints = false
    label.textAlignment = NSTextAlignment.Center

    addSubview(label)

    NSLayoutConstraint.activateConstraints([
        personView.topAnchor.constraintEqualToAnchor(topAnchor),
        personView.leadingAnchor.constraintEqualToAnchor(leadingAnchor),
        personView.trailingAnchor.constraintEqualToAnchor(trailingAnchor),
        personView.bottomAnchor.constraintEqualToAnchor(label.topAnchor),
        label.leadingAnchor.constraintEqualToAnchor(leadingAnchor),
        label.trailingAnchor.constraintEqualToAnchor(trailingAnchor),
        label.heightAnchor.constraintEqualToConstant(frame.size.height*0.25),
        label.bottomAnchor.constraintEqualToAnchor(bottomAnchor)
        ])





所以目前我的DetailedPersonView 的TokenView(嵌套在PersonView 中)显示了PersonView 的默认tokenName 和tokenImage,即“Bob”,反映PersonGroup.Bad 的圆圈轮廓也是如此。

我尝试使用 PersonView 的自定义 init 方法,尝试使用DetailedPersonView 的变量初始化DetailedPersonView 中的PersonView,但成功有限。

理想情况下,这个自定义子视图应该类似于 UILabel 的工作方式,其中 UILabel().text 会随着变量的变化而更改视图中的文本,如果这有意义的话。

目前还没有找到解决这个问题的明确方法:\

感谢您阅读此问题! :D

编辑: 我认为可能有效的一种解决方法是为自定义 UIView 实现一个类方法来重置每个子视图的内容,并在每次更改变量时调用它。或者委托中是否已经有一个可以实现相同结果的函数,并且在视图更改时被调用?

【问题讨论】:

【参考方案1】:

您正在更改子视图的属性,但没有将这些更改传播到依赖这些属性的子视图。这通常通过属性观察来快速完成。有关更多信息,请参阅财产观察员部分here。但是您可以使用didSetobserver 来传播您的更改。例如,在您的 PersonView 类中,您应该首先保留对它的引用 TokenView 子视图 var tokenView:TokenView? 并且它是 UILabel subviewvar nameLabel:UILabel?and set them equal to theTokenViewandUILabelyou create inmakePersonView`。然后在名称上添加属性观察:

    var name: String?
        didSet
            if let image = UIImage(named: name!)
            
                self.tokenView?.tokenImage = image
                self.nameLabel?.text = name
                self.tokenView?.setNeedsDisplay()
            
        
    

这样DetailPersonView 对名称的任何更改都会自动更改TokenView's 图像。

tokenImagetokenOutlineColor 类似,您需要在每次设置它们时重新绘制视图。

   @IBInspectable var tokenOutlineColor: UIColor = UIColor.blackColor()
        didSet
            self.setNeedsDisplay()
        
    
    @IBInspectable var tokenImage: UIImage!
        didSet
            self.setNeedsDisplay()
        
    

【讨论】:

以上是关于在另一个自定义 UIView 中设置/更改嵌套自定义 UIView 的变量的主要内容,如果未能解决你的问题,请参考以下文章

工程日记之HelloSlide:Swift自定义可视化组件的方法(继承UIView和在StoryBoard中设置)

在自定义单元格中设置自定义附件类型

iOS:如何获取刚刚在界面生成器中设置的 UIView 的框架

在TextView中设置文本自定义

JS/jQuery:使用下拉框在另一个字段中设置值,是不是正在更改以前的字段?

如何在 ListView 和 AlertDialog 中设置自定义字体?