免责声明:谈论代表时我的术语可能有些偏差。
我已经调试了几个小时了,虽然我发现了一些有趣的行为。基本上我有一个UIViewController(VC),其自定义NSObject(NSO)实例作为属性。我在NSO对象中创建了一个委托,以便它可以在VC中通话/调用函数。之前我已经这样做了,所以我认为这没问题,但是当我尝试从NSO对象调用委托函数时,VC不接收调用。
这是我的NSO课程的界面
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <Parse/Parse.h>
#import <MobileCoreServices/MobileCoreServices.h>
@protocol ServerDBDelegate <NSObject>
@required
- (void) func;
@end
@interface ServerDB : NSObject <CLLocationManagerDelegate>
@property (nonatomic, retain) id<ServerDBDelegate> delegate;
@end
NSO对象使用CoreLocation,我从一个CoreLocation委托函数调用VC委托函数,特别是......
-(void)locationManager: didUpdateLocations: {
[self.delegate func];
}
如果这令人困惑,请发表评论,我会澄清。
由于VC从未收到我在此行中放入上述函数的调用。
NSLog(self.delegate == nil ? @"Nil" : @"Not nil");
这会每次打印'Nil'所以我认为我没有正确设置我的代表。经过更多的调试后,我仍然认为我正在正确地执行委托,所以我覆盖了委托的setter,看看它是否在某些时候设置正确。
- (void) setDelegate:(id<ServerDBDelegate>)delegate {
_delegate = delegate;
NSLog(self.delegate == nil ? "Nil2" : "Not Nil2");
}
当setter被调用时,它输出'Not Nil2',然后一瞬间我看到了CoreLocation委托函数的输出'Nil'。所以我认为我最初正确设置了委托,但在某些时候它被覆盖为零。好的,我的最后一步。
- (void) setDelegate:(id<ServerDBDelegate>)delegate {
_delegate = delegate;
[self performSelector:@selector(test) withObject:self afterDelay:3];
}
- (void) test {
NSLog(self.delegate == nil ? "Nil2" : "Not Nil2");
}
-(void)locationManager: didUpdateLocations: {
NSLog(self.delegate == nil ? "Nil" : "Not Nil");
[self test];
}
重要的是要知道,locationManager函数每秒被调用几次。所以当我运行它时,我看到了这个输出
Nil
Nil2
Nil
Nil2
Nil
Nil2
Nil
Nil2
Not Nil2
Nil
Nil2
所以看起来代理没有设置,但是当我调用test时:在设置器延迟之后它仍然被设置,但仅在该函数的范围内。我真的不知道如何继续或错误可能在哪里。提前感谢您的帮助。
答案 0 :(得分:0)
我认为你误解了代表的工作方式。
但在进一步讨论之前我有一个问题:你没有使用ARC?我看到您在委托属性上使用了retain
。
无论哪种方式,如果您使用retain
作为代理属性(在ARC下为strong
而不是weak
),您将创建保留周期
现在回到你的问题:
你是如何宣布协议和委托的(除了它应该在ARC下分配或弱)。
这个方法对我来说几乎没问题:
-(void)locationManager: didUpdateLocations: {
[self.delegate func];
}
但作为一种良好做法,您应该始终检查您的代表respondsToSelector
。因此,请if
语句包含[self.delegate func]
,如此:if ([self.delegate respondsToSelector:@selector(func)]){self.delegate func];}
如果要符合委托,在应该符合它的类中,必须将ServerDBDelegate
添加到其接口声明中,如下所示:
@interface myClass: superclass <ServerDBDelegate>
在宣布您的班级符合ServerDBDelegate
后,您必须通过以下方式致电该班级的代表:
[[ServerDB sharedManager] setDelegate: self]; //example of a singleton class setDelegate call.
或者在符合ServerDBDelegate的类中具有ServerDB属性(非原子,强),在类中的某个地方实例化它(viewDidLoad
将是一个很好的候选者)或者做一个懒惰的实例化并成为委托像这样的ServerDB类:
头文件(.h):
@interface myClassViewController: UIViewController <ServerDBDelegate>
@end
实施文件(.m)
@interface myClassViewController ()
@property (nonatomic, strong) ServerDB *dbInstance; //hold a strong reference to the ServerDBClass
@end
@implementation myClassViewController
//lazy instantiation
- (ServerDB *)dbInstance {
if (_dbInstance) {return _dbInstance;}
_dbInstance = [[ServerDB alloc] init];
return _dbInstance;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.dbInstance.delegate = self; //here you make myClassViewController a delegate of your ServerDB class
}
//add and define the required method from your delegate protocol
- (void)func {
NSLog(@"ServerDB called me: %@",NSStringFromSelector:@selector(_cmd));
}
@end
现在,每当你在ServerDB类中调用委托'func'方法时,委托就会调用myClassViewController中定义的'func'方法。