InterfaceBuilder声明的UIView子类方法调用异常求助
解决IB创建自定义View时setProgressValue无响应&代码初始化视图不更新问题
嘿,我帮你梳理下这个自定义View的问题,你遇到的两种场景(IB创建无响应、代码初始化视图不更新)其实都是自定义UIView开发里的常见坑,咱们一步步来排查解决:
一、先搞定IB Outlet无响应的问题
首先你提到用weak IBOutlet调用方法没反应,很大概率是Outlet没正确连接,或者对象被提前释放了:
- 先检查Storyboard/XIB的连接:右键你的ViewController类里的IBOutlet属性,看看它是不是真的指向了IB里的那个
IVVerticalProgress实例,有时候拖拽连接可能没成功,或者不小心断开了。 - 把
weak改成strong试试:自定义View用weak修饰Outlet很容易因为父视图的引用关系被提前释放,改成strong能避免这个问题:@property (nonatomic, strong) IBOutlet IVVerticalProgress *verticalProgressView; - 调用方法前先打印对象:确认它不是
nil,如果打印出来是nil,那肯定是连接或者释放的问题:NSLog(@"当前progressView实例:%@", self.verticalProgressView); [self.verticalProgressView setProgressValue:50];
二、确保自定义View的初始化逻辑覆盖所有场景
IB创建的View和代码初始化的View走的是不同的初始化方法,你的IVVerticalProgress必须在所有初始化入口都做好基础设置,不然会导致逻辑缺失:
@implementation IVVerticalProgress // 代码初始化走这个方法 - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self commonInit]; } return self; } // IB初始化走这个方法 - (instancetype)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; if (self) { [self commonInit]; } return self; } // IB加载完成后会调用这个方法,做后续初始化 - (void)awakeFromNib { [super awakeFromNib]; [self commonInit]; } // 统一的初始化逻辑写在这里 - (void)commonInit { // 比如设置默认背景色、初始化子视图、设置进度默认值 self.backgroundColor = [UIColor lightGrayColor]; self.progressValue = 0; } @end
三、修复setProgressValue方法的视图更新逻辑
不管是IB还是代码创建的View,调用setProgressValue:后都需要主动触发视图重绘或者布局更新,不然UI不会变化:
- (void)setProgressValue:(CGFloat)progressValue { // 先把进度值限制在0-100的合理范围 _progressValue = MAX(0, MIN(100, progressValue)); NSLog(@"进度已更新为:%.2f", _progressValue); // 如果是用drawRect:绘制的进度条,触发重绘 [self setNeedsDisplay]; // 如果是用子视图(比如一个UIView作为进度条),触发布局更新 [self setNeedsLayout]; }
四、代码初始化时的视图显示问题
你说代码初始化方法能执行但视图不更新,大概率是没把视图添加到父视图层级,或者布局没设置好:
// 代码创建并添加视图 IVVerticalProgress *progressView = [[IVVerticalProgress alloc] initWithFrame:CGRectMake(50, 50, 20, 200)]; // 一定要添加到父视图! [self.view addSubview:progressView]; // 如果你用AutoLayout,记得关掉自动转换约束 progressView.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ [progressView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:50], [progressView.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:50], [progressView.widthAnchor constraintEqualToConstant:20], [progressView.heightAnchor constraintEqualToConstant:200] ]]; // 现在再设置进度就会生效了 [progressView setProgressValue:50];
额外提示(针对IB_DESIGNABLE)
你用到了IB_DESIGNABLE,如果IB里看不到自定义View的预览,试试**Clean Build Folder(Cmd+Shift+K)**后重新编译,Xcode有时候会缓存旧的自定义View代码,导致预览不更新。
另外,如果你的进度条是用drawRect:绘制的,要确保在drawRect:里正确使用了progressValue:
- (void)drawRect:(CGRect)rect { [super drawRect:rect]; // 计算进度条的高度 CGFloat progressHeight = rect.size.height * (self.progressValue / 100.0); // 绘制进度条的区域 CGRect progressRect = CGRectMake(0, rect.size.height - progressHeight, rect.size.width, progressHeight); [[UIColor blueColor] setFill]; UIRectFill(progressRect); }
内容的提问来源于stack exchange,提问作者Benjamin de Bos
相关产品推荐
相关产品推荐

