Objective-C self.delegate 设置后为空
Objective-C self.delegate is null after being set
我已经为 UIView 设置了一个非常简单的委托。但是,当我尝试这样做时:
if ([self.delegate respondsToSelector:@selector(selectedPlayTrailer:)]){
[self.delegate selectedPlayTrailer:self];
}
我的 self.delegate 为空。我检查了 setter 被设置为代表的 class 是正确的:
- (void)setDelegate:(id<MyViewDelegate>)delegateClass
{
// Whether I overwrite this method or not, it's still null.
NSLog(@"%@", delegate);
_delegate = delegateClass;
}
这是正确的。但是当它在我的 IBAction 中被调用时 - 它是空的。
编辑:澄清一下,我只是将其放入以查看传入的内容。如果我不覆盖此方法,它仍然为空。
我的代码:
MyView.h
#import <UIKit/UIKit.h>
@class MyView;
@protocol MyViewDelegate <NSObject>
@optional
- (void) myDelegateMethod:(MyView *)sender;
@end
@interface MyView : UIView
@property (nonatomic, weak) id <MyViewDelegate> delegate;
- (IBAction)myButton:(id)sender;
@end
MyView.m
@implementation MyView
@synthesize delegate;
- (id)init
{
if (!(self = [super init])) return nil;
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"MyView"
owner:self
options:nil];
return self;
}
- (IBAction)myButton:(id)sender
{
// NOTE: Here, self.delegate is null
if ([self.delegate respondsToSelector:@selector(myDelegateMethod:)]){
[self.delegate myDelegateMethod:self];
}
}
@end
MyCollectionViewCell.m
#import "MyCollectionViewCell.h"
#import "MyView.h"
@interface MyCollectionViewCell() <MyViewDelegate>
@property (nonatomic, strong) MyView *myView;
@end
@implementation MyCollectionViewCell
@synthesize myView;
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self){
[self setup];
}
return self;
}
- (void)setup
{
self.myView = [MyView new];
self.myView.frame = CGRectMake(0,0,self.bounds.size.width, self.bounds.size.height);
self.myView.alpha = 0.0;
self.myView.layer.cornerRadius = 5.0f;
self.myView.layer.masksToBounds = YES;
self.myView.delegate = self;
[self addSubview:self.myView];
}
// The delegate method
- (void)myDelegateMethod:(MyView *)sender
{
NSLog(@"This is never called...");
}
@end
向 MyCollectionViewCell
添加:
- (void)dealloc
{
NSLog(@"MyCollectionViewCell dealloc called")
}
delegate
是弱引用。因此,如果设置为 delegate
的实例被释放,它将变为 nil。以上的目的是确认这种情况正在发生。
为什么会这样?如果没有任何东西维护对 MyCollectionViewCell
实例的强引用,那么它将被释放。
理想情况下,您还想添加一个 NSLog
到 myButtonPressed:
。如果您 NSLog
'd 委托的设置,这也会有所帮助。所以你的输出可能是这样的:
Delegate set
MyCollectionViewCell dealloc called <- this would indicate that the delegate becomes nil based on the instance being released
myButtonPressed: hit
鉴于您提供的信息量,这是一个可行的理论。
将 viewcontroller 设置为 MyView 对象的委托而不是集合视图单元格。
在您的视图控制器中,在数据源方法中
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
做这样的事情。
cell.myView.delegate = self;
更新
据观察,问题出在分配 UIView
子类中。将视图初始化为
self.myView = [MyView new];
由于某种原因无法使用。要正确分配视图,可以使用 following approach。
self.myView = [[[NSBundle mainBundle]
loadNibNamed:@"MyView"
owner:self options:nil]
firstObject];
我已经为 UIView 设置了一个非常简单的委托。但是,当我尝试这样做时:
if ([self.delegate respondsToSelector:@selector(selectedPlayTrailer:)]){
[self.delegate selectedPlayTrailer:self];
}
我的 self.delegate 为空。我检查了 setter 被设置为代表的 class 是正确的:
- (void)setDelegate:(id<MyViewDelegate>)delegateClass
{
// Whether I overwrite this method or not, it's still null.
NSLog(@"%@", delegate);
_delegate = delegateClass;
}
这是正确的。但是当它在我的 IBAction 中被调用时 - 它是空的。
编辑:澄清一下,我只是将其放入以查看传入的内容。如果我不覆盖此方法,它仍然为空。
我的代码:
MyView.h
#import <UIKit/UIKit.h>
@class MyView;
@protocol MyViewDelegate <NSObject>
@optional
- (void) myDelegateMethod:(MyView *)sender;
@end
@interface MyView : UIView
@property (nonatomic, weak) id <MyViewDelegate> delegate;
- (IBAction)myButton:(id)sender;
@end
MyView.m
@implementation MyView
@synthesize delegate;
- (id)init
{
if (!(self = [super init])) return nil;
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"MyView"
owner:self
options:nil];
return self;
}
- (IBAction)myButton:(id)sender
{
// NOTE: Here, self.delegate is null
if ([self.delegate respondsToSelector:@selector(myDelegateMethod:)]){
[self.delegate myDelegateMethod:self];
}
}
@end
MyCollectionViewCell.m
#import "MyCollectionViewCell.h"
#import "MyView.h"
@interface MyCollectionViewCell() <MyViewDelegate>
@property (nonatomic, strong) MyView *myView;
@end
@implementation MyCollectionViewCell
@synthesize myView;
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self){
[self setup];
}
return self;
}
- (void)setup
{
self.myView = [MyView new];
self.myView.frame = CGRectMake(0,0,self.bounds.size.width, self.bounds.size.height);
self.myView.alpha = 0.0;
self.myView.layer.cornerRadius = 5.0f;
self.myView.layer.masksToBounds = YES;
self.myView.delegate = self;
[self addSubview:self.myView];
}
// The delegate method
- (void)myDelegateMethod:(MyView *)sender
{
NSLog(@"This is never called...");
}
@end
向 MyCollectionViewCell
添加:
- (void)dealloc
{
NSLog(@"MyCollectionViewCell dealloc called")
}
delegate
是弱引用。因此,如果设置为 delegate
的实例被释放,它将变为 nil。以上的目的是确认这种情况正在发生。
为什么会这样?如果没有任何东西维护对 MyCollectionViewCell
实例的强引用,那么它将被释放。
理想情况下,您还想添加一个 NSLog
到 myButtonPressed:
。如果您 NSLog
'd 委托的设置,这也会有所帮助。所以你的输出可能是这样的:
Delegate set
MyCollectionViewCell dealloc called <- this would indicate that the delegate becomes nil based on the instance being released
myButtonPressed: hit
鉴于您提供的信息量,这是一个可行的理论。
将 viewcontroller 设置为 MyView 对象的委托而不是集合视图单元格。
在您的视图控制器中,在数据源方法中
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
做这样的事情。
cell.myView.delegate = self;
更新
据观察,问题出在分配 UIView
子类中。将视图初始化为
self.myView = [MyView new];
由于某种原因无法使用。要正确分配视图,可以使用 following approach。
self.myView = [[[NSBundle mainBundle]
loadNibNamed:@"MyView"
owner:self options:nil]
firstObject];