在另一个自定义 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。但是您可以使用didSet
observer 来传播您的更改。例如,在您的 PersonView
类中,您应该首先保留对它的引用 TokenView
子视图 var tokenView:TokenView?
并且它是 UILabel subview
var nameLabel:UILabel?and set them equal to the
TokenViewand
UILabelyou create in
makePersonView`。然后在名称上添加属性观察:
var name: String?
didSet
if let image = UIImage(named: name!)
self.tokenView?.tokenImage = image
self.nameLabel?.text = name
self.tokenView?.setNeedsDisplay()
这样DetailPersonView
对名称的任何更改都会自动更改TokenView's
图像。
与tokenImage
和tokenOutlineColor
类似,您需要在每次设置它们时重新绘制视图。
@IBInspectable var tokenOutlineColor: UIColor = UIColor.blackColor()
didSet
self.setNeedsDisplay()
@IBInspectable var tokenImage: UIImage!
didSet
self.setNeedsDisplay()
【讨论】:
以上是关于在另一个自定义 UIView 中设置/更改嵌套自定义 UIView 的变量的主要内容,如果未能解决你的问题,请参考以下文章
工程日记之HelloSlide:Swift自定义可视化组件的方法(继承UIView和在StoryBoard中设置)
iOS:如何获取刚刚在界面生成器中设置的 UIView 的框架