Delegate未触发方法:SquareView代理调用返回nil问题排查
Delegate代理未触发问题排查与修复
问题描述
我查了其他Delegate相关问题,但没找到合适的解决方案。所有配置看起来正常,滑块数值变化能在日志里看到,但SquareView调用numberOfSquaresInSquareView()方法时从未触发,而且SquareView的代理调用返回nil。changeSquareCount()方法能正常工作,日志显示数值已成功保存,我觉得已经接近解决但漏了些细节。
相关代码
squareView.h
#import <Cocoa/Cocoa.h> NS_ASSUME_NONNULL_BEGIN @class SquareView; @protocol SquareViewDelegate <NSObject> - (NSNumber *)numberOfSquaresInSquareView:(SquareView *)squareView; @end @interface SquareView : NSView @property (nonatomic, weak) id<SquareViewDelegate> delegate; @end NS_ASSUME_NONNULL_END
squareView.m
#import "SquareView.h" @implementation SquareView @synthesize delegate; - (id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; if (self) { } return self; } - (void)drawRect:(NSRect)dirtyRect { [super drawRect:dirtyRect]; NSLog(@"drawing rect"); [[NSColor redColor]set]; //NSNumber *num = ; //cound pass in nil, dont matter NSLog(@"squares to draw: %@", [delegate numberOfSquaresInSquareView:self]); // Drawing code here. } @end
AppController.h
#import <Foundation/Foundation.h> #import "SquareView.h" //@class SquareView; NS_ASSUME_NONNULL_BEGIN @interface AppController : NSObject <SquareViewDelegate> @property (retain) IBOutlet SquareView *squareView; - (IBAction)changeSquareCount:(id)sender; @end NS_ASSUME_NONNULL_END
AppController.m
#import "AppController.h" @implementation AppController { NSNumber *_squareCount; } @synthesize squareView = _squareView; - (void)awakeFromNib { [_squareView setDelegate:nil]; _squareCount = @(10); [_squareView setNeedsDisplay:YES]; } - (void)changeSquareCount:(id)sender { _squareCount = @([sender intValue]); NSLog(@"square count stored: %@",_squareCount); [_squareView setNeedsDisplay:YES]; } -(NSNumber *)numberOfSquaresInSquareView:(SquareView *) squareView { NSLog(@"triggering numberOfSquaresInSquareView"); return _squareCount; } @end
修复方案
1. 修正代理赋值错误
问题核心在AppController的awakeFromNib方法中——你将_squareView的代理设置为nil,导致SquareView无法找到代理对象调用方法。只需将代理设为self即可:
- (void)awakeFromNib { [_squareView setDelegate:self]; // 替换原有的nil为self _squareCount = @(10); [_squareView setNeedsDisplay:YES]; }
2. 增加代理安全判断(可选但推荐)
在SquareView的drawRect方法中,调用代理前先判断代理是否存在且响应目标方法,避免因代理为空导致崩溃:
- (void)drawRect:(NSRect)dirtyRect { [super drawRect:dirtyRect]; NSLog(@"drawing rect"); [[NSColor redColor]set]; NSNumber *squareNum = nil; // 先判断代理是否响应方法 if ([self.delegate respondsToSelector:@selector(numberOfSquaresInSquareView:)]) { squareNum = [self.delegate numberOfSquaresInSquareView:self]; } NSLog(@"squares to draw: %@", squareNum); // Drawing code here. }
3. 规范属性访问(可选)
在SquareView中建议使用self.delegate而非直接访问实例变量delegate,符合Objective-C属性访问的最佳实践。
内容的提问来源于stack exchange,提问作者Hyperian
相关产品推荐
相关产品推荐

