UISwitch添加跨类实例对象为target时回调失效问题求助
原因分析
你遇到的问题核心是ARC内存管理机制导致的:
- 在无效代码中,
[CustomClass alloc]创建的实例对象没有被任何强引用持有,ARC会在当前代码执行完毕后立即释放这个实例。当UISwitch触发UIControlEventValueChanged事件时,目标对象已经被销毁,自然无法调用实例方法test。 - 类对象是全局唯一的单例对象,系统会一直持有它的强引用,不会被ARC释放,所以绑定类方法时,事件触发时目标对象始终存在,方法能正常执行。
解决方案
要让跨类实例方法正常被UISwitch调用,核心是保证target实例被强引用持有,常见的实现方式有两种:
方案1:将CustomClass实例声明为当前类的属性
在当前类的实现文件中添加强引用属性:
@property (strong, nonatomic) CustomClass *customInstance;
然后在创建UISwitch时,先初始化并持有这个实例:
@implementation CustomClass : NSObject -(void) test { NSLog(@"TEST"); } @end // 在当前类的方法中 self.customInstance = [[CustomClass alloc] init]; UISwitch *uiSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(100, 100, 50, 50)]; [uiSwitch addTarget:self.customInstance action:@selector(test) forControlEvents:UIControlEventValueChanged]; [self addSubview:uiSwitch];
方案2:使用单例模式复用CustomClass实例
如果CustomClass的实例可以全局复用,将其设计为单例:
@implementation CustomClass : NSObject +(instancetype)sharedInstance { static CustomClass *instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[CustomClass alloc] init]; }); return instance; } -(void) test { NSLog(@"TEST"); } @end
绑定target时直接使用单例对象:
UISwitch *uiSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(100, 100, 50, 50)]; [uiSwitch addTarget:[CustomClass sharedInstance] action:@selector(test) forControlEvents:UIControlEventValueChanged]; [self addSubview:uiSwitch];
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

