Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 在另一个自定义UIView中设置/更改嵌套自定义UIView的变量_Swift_Variables_Uiview_Nested - Fatal编程技术网

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

Swift 在另一个自定义UIView中设置/更改嵌套自定义UIView的变量,swift,variables,uiview,nested,Swift,Variables,Uiview,Nested,我目前在其他自定义UIView中嵌套的自定义UIView中遇到问题,嵌套的自定义UIView的变量无法更改,因此无法反映在视图本身中 目前,我有3个自定义UIView: TokenView,它仅覆盖drawRect以生成一个圆中包含图像的视图 @IBDesignable class TokenView: UIView { @IBInspectable var tokenOutlineColor: UIColor = UIColor.blackColor() @IBInspectable var

我目前在其他自定义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()。文本在视图中随变量的变化而变化(如果有意义的话)

到目前为止,尚未找到解决此问题的明确方法:\

感谢您阅读此问题!:D

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

您正在更改子视图上的属性,但不会将这些更改传播到依赖于这些属性的子视图。在swift中,这通常是通过观察属性来完成的。有关详细信息,请参见“属性观察者”部分。但是您可以使用
didSet
observer来传播您的更改。例如,在您的
PersonView
类中,您应该首先保留对它的
TokenView
子视图
var TokenView:TokenView?
和它的
UILabel子视图
var nameLabel:UILabel?
的引用,并将它们设置为与您在
makePersonView`中创建的
TokenView
UILabel
相等。然后在名称上添加属性:

    var name: String?{
        didSet{
            if let image = UIImage(named: name!)
            {
                self.tokenView?.tokenImage = image
                self.nameLabel?.text = name
                self.tokenView?.setNeedsDisplay()
            }
        }
    }
这样,
DetailPersonView
对name的任何更改都将自动更改
TokenView的图像

类似地,对于
tokenImage
tokenOutlineColor
您需要在每次设置视图时重新绘制视图

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

您正在更改子视图上的属性,但不会将这些更改传播到依赖于这些属性的子视图。在swift中,这通常是通过观察属性来完成的。有关详细信息,请参见“属性观察者”部分。但是您可以使用
didSet
observer来传播您的更改。例如,在您的
PersonView
类中,您应该首先保留对它的
TokenView
子视图
var TokenView:TokenView?
和它的
UILabel子视图
var nameLabel:UILabel?
的引用,并将它们设置为与您在
makePersonView`中创建的
TokenView
UILabel
相等。然后在名称上添加属性:

    var name: String?{
        didSet{
            if let image = UIImage(named: name!)
            {
                self.tokenView?.tokenImage = image
                self.nameLabel?.text = name
                self.tokenView?.setNeedsDisplay()
            }
        }
    }
这样,
DetailPersonView
对name的任何更改都将自动更改
TokenView的图像

类似地,对于
tokenImage
tokenOutlineColor
您需要在每次设置视图时重新绘制视图

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