Skip to main content
 首页 » 操作系统

ios之使用 setNeedsDisplay 更新 UIView 不起作用

2024年01月01日47unruledboy

我的应用程序中有一个圆形进度条,显示用户已花费预算的百分比。每次用户切换到带有圆形进度条的 View 时,进度条都应该更新。它也应该在用户每次打开应用时更新。

目前,由于某种我无法理解的原因,它只会在应用程序打开时更新(从在多任务处理中关闭)并且如果用户切换到该 View (它应该)永远不会更新。我进行了大量研究,但未能找到解决方案。

这是创建圆的代码:

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() 
} 

我真的希望有人能提供解决方案,因为我已经遇到这个问题大约一个星期了。谢谢。

请您参考如下方法:

每次您的 View Controller 出现并调用 viewDidAppear() 时,您都在创建一个全新 ProgressCircle View 并将其发送到背部。除非您在其他地方这样做,否则您似乎从未从 budgetDisplayView 中删除 ProgressCircle。我说得对吗?

如果我是对的,当应用程序从完全关闭打开时,viewDidAppear() 将在该 View Controller 上第一次被调用,并且 单个 进度将在您观察时创建并显示圆圈。下次显示该 View Controller 并再次调用 viewDidAppear() 时,将创建另一个进度圈并添加到上次创建的进度圈后面!以后每次都会发生同样的事情。我想这就是你看不到它的原因。作为快速测试(但不是长期解决方案),请尝试注释行:self.budgetDisplayView.sendSubviewToBack(circle)。希望对您有所帮助。