IOS委托函数没有被调用

时间:2015-01-20 02:02:33

标签: ios delegates core-location

免责声明:谈论代表时我的术语可能有些偏差。

我已经调试了几个小时了,虽然我发现了一些有趣的行为。基本上我有一个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时:在设置器延迟之后它仍然被设置,但仅在该函数的范围内。我真的不知道如何继续或错误可能在哪里。提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我认为你误解了代表的工作方式。 但在进一步讨论之前我有一个问题:你没有使用ARC?我看到您在委托属性上使用了retain

无论哪种方式,如果您使用retain作为代理属性(在ARC下为strong而不是weak),您将创建保留周期

现在回到你的问题:

  1. 你是如何宣布协议和委托的(除了它应该在ARC下分配或弱)。

  2. 这个方法对我来说几乎没问题:

    -(void)locationManager: didUpdateLocations: { [self.delegate func]; }

  3. 但作为一种良好做法,您应该始终检查您的代表respondsToSelector。因此,请if语句包含[self.delegate func],如此:if ([self.delegate respondsToSelector:@selector(func)]){self.delegate func];}

    1. 如果要符合委托,在应该符合它的类中,必须将ServerDBDelegate添加到其接口声明中,如下所示:

      @interface myClass: superclass <ServerDBDelegate>

    2. 在宣布您的班级符合ServerDBDelegate后,您必须通过以下方式致电该班级的代表:

    3. [[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'方法。