使用setNeedsDisplay更新UIView不起作用

问题描述:

我在我的应用程序中有一个循环进度栏,显示他们花费的用户预算的百分比。每次用户切换到带有圆形进度条的视图时,进度条都应该更新。它也应该每次用户打开应用程序时进行更新。使用setNeedsDisplay更新UIView不起作用

目前,由于某些原因,我不明白,它只会在应用程序打开时(从多任务关闭时)更新,如果用户切换到该视图(它应该),它将永远不会更新。我已经完成了大量的研究,但一直未能找到解决方案。

下面是创建圆代码:

var progress: CGFloat = 0 

class ProgressCircle: UIView { 

override func drawRect(rect: CGRect) { 
    var ctx = UIGraphicsGetCurrentContext() 

    var innerRadiusRatio: CGFloat = 0.6 

    var path: CGMutablePathRef = CGPathCreateMutable() 
    var startAngle: CGFloat = CGFloat(-M_PI_2) 
    var endAngle: CGFloat = CGFloat(-M_PI_2) + min(1.0, progress) * CGFloat(M_PI * 2) 
    var outerRadius: CGFloat = CGRectGetWidth(self.bounds) * 0.5 - 1.0 
    var innerRadius: CGFloat = outerRadius * innerRadiusRatio 
    var center = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)) 

    //Code for background circle 

    var context: CGContextRef = UIGraphicsGetCurrentContext() 
    colourTheme = NSUserDefaults.standardUserDefaults().integerForKey("themeSettings") 
    if colourTheme == 1 { 
     CGContextSetFillColorWithColor(context, (UIColorFromRGB(0xEAEAEA)).CGColor) 
    } else { 
     CGContextSetFillColorWithColor(context, (UIColor.darkGrayColor()).CGColor) 
    } 

    var circleSize: CGFloat = 0 
    switch height { 
    case 480, 568: 
     circleSize = 171 
    default: 
     circleSize = 250 
    } 

    var rectangle: CGRect = CGRectMake(0, 0, circleSize, circleSize) 
    CGContextBeginPath(context) 
    CGContextAddEllipseInRect(context, rectangle) 
    CGContextDrawPath(context, kCGPathFill) 

    UIGraphicsEndImageContext() 

    if colourTheme == 1 { 
     CGContextSetFillColorWithColor(context, (UIColor.darkGrayColor()).CGColor) 
    } else { 
     CGContextSetFillColorWithColor(context, (UIColorFromRGB(0xEAEAEA)).CGColor) 
    } 

    var circleXY: CGFloat = 0 
    var circleWH: CGFloat = 0 
    switch height { 
    case 480, 568: 
     circleXY = 35.95 
     circleWH = 99.1 
    default: 
     circleXY = 52 
     circleWH = 146 
    } 
    var rectangleSmall: CGRect = CGRectMake(circleXY, circleXY, circleWH, circleWH) //102.6 
    CGContextBeginPath(context) 
    CGContextAddEllipseInRect(context, rectangleSmall) 
    CGContextDrawPath(context, kCGPathFill) 

    UIGraphicsEndImageContext() 

    //Code for progress radius 

    CGPathAddArc(path, nil, center.x, center.y, innerRadius, startAngle, endAngle, false) 
    CGPathAddArc(path, nil, center.x, center.y, outerRadius, endAngle, startAngle, true) 
    CGPathCloseSubpath(path) 
    CGContextAddPath(ctx, path) 

    CGContextSaveGState(ctx) 
    CGContextClip(ctx) 
    if percent > 100 { 
     CGContextDrawImage(ctx, self.bounds, UIImage(named: "RadialProgressFillOver").CGImage) 
    } else { 
     CGContextDrawImage(ctx, self.bounds, UIImage(named: "RadialProgressFill").CGImage) 
    } 
    CGContextRestoreGState(ctx) 
} 

这里是我使用的(尝试)来更新进度圈的代码。此代码是在viewDidAppear():

override func viewDidAppear(animated: Bool) { 
    //Show set up screen if user hasn't used AffordIt before. 

    userReturned = NSUserDefaults.standardUserDefaults().boolForKey("userReturnedCheck") 
    if userReturned == false { 
     self.performSegueWithIdentifier("setupView", sender: self) 
    } 

    //Add circular progress bar to budget display view. 

    var circleSize: CGFloat = 0 
    var yCoord: CGFloat = 0 
    switch height { 
    case 480, 568: 
     circleSize = 171 
     yCoord = 249 
    case 667: 
     circleSize = 250 
     yCoord = 249 
    default: 
     circleSize = 250 
     yCoord = 279 
    } 

    progress = CGFloat(percent/100) 
    var circleFrame = CGRect(x: (budgetDisplayView.bounds.width/2)-(circleSize/2), y: yCoord, width: circleSize, height: circleSize) 
    var circle = ProgressCircle(frame: circleFrame) 
    self.budgetDisplayView.addSubview(circle) 
    self.budgetDisplayView.sendSubviewToBack(circle) 
    circle.setNeedsDisplay() 
    view.setNeedsDisplay() 

    circle.backgroundColor = UIColor.clearColor() 
} 

我真的希望有人有一个解决方案,因为我现在已经没有这个问题了大约一个星期。谢谢。

出现在您的视图控制器每次和viewDidAppear()叫,你要创建一个全新ProgressCircle视图,并将其发送到后面。除非你在其他地方做,否则你不会从budgetDisplayView中删除ProgressCircle。我对吗?

如果我是正确的,当应用程序是被完全封闭打开,viewDidAppear()将被称为首次这一观点控制器和进展圈将被创建并为你观察所示。下次显示视图控制器时,将再次调用viewDidAppear()另一个创建进度圆圈并将其添加到上次创建的圆圈后面!同样的事情发生在随后的每一次。我认为这就是为什么你看不到它。作为快速测试(但不是长期解决方案),请尝试评论该行:self.budgetDisplayView.sendSubviewToBack(circle)。希望有所帮助。

+0

哇。这确实是问题!我从来没有注意到,所以非常感谢! – user3746428 2014-10-07 13:24:28