0

I have a CLLocationManager singleton which implements a protocol, so I can tell another model class (ServerConnection) that an updated location of the user has been found.

In my AppDelegate in the method, didFinishLaunching, I write

ServerConnection* serverConnection = [[ServerConnection alloc] init];
[LocationManager sharedLocationSingleton].delegate = serverConnection;
[[LocationManager sharedLocationSingleton] getUsersLocation];

This doesn't work and the delegate method in my ServerConnection class isn't called. However, if I try having my AppDelegate class be the listener, as in the following line, it works fine.

// self refers to AppDelegate
[LocationManager sharedLocationSingleton].delegate = self;

Here, my AppDelegate implements the required delegate method and the method is called when the user's location is updated, as it should.

Why is my above method failing, where I try to set the delegate to be serverConnection?

Tutorials online usually point to using a UIViewController or the AppDelegate as the "listener", but in my case, I want a separate model class to be the listener. How do I do that?

Below is my LocationManager singleton class with the protocol

@class LocationManager;

@protocol LocationManagerDelegate <NSObject>
@required
-(void)LocationManagerUpdated:(LocationManager*) locationManager
                  withValue:(CLLocation*) location;
@end

@interface LocationManager : NSObject <CLLocationManagerDelegate>

@property (strong, nonatomic) CLLocationManager* locationManager;
@property (strong, nonatomic) CLLocation* location;
@property (weak, nonatomic) id <LocationManagerDelegate> delegate;

+(LocationManager*)sharedLocationSingleton;
-(void) getUsersLocation;

@end

My header file for Server connection is.

#import <Foundation/Foundation.h>
#import "LocationManager.h"

@interface ServerConnection : NSObject <LocationManagerDelegate>
@end

This works when AppDelegate is set to be the listener, but not my model object ServerConnection. How do I fix this?

Thanks!

Rohan Agarwal
  • 2,167
  • 1
  • 24
  • 34

2 Answers2

0

There should be no problem in doing what you are trying to do (i.e., having a non-controller class instance to act as a delegate).

This works when AppDelegate is set to be the listener, but not my model object ServerConnection.

Does your ServerConnection class implement the LocationManagerDelegate protocol? (I mean implement as opposed to just declare it in its interface).

Check the LocationManager method in charge for calling the delegate method (LocationManagerUpdated:) and add there a NSLog trace to check that the delegate object is correctly set when you try and send it the message.

EDIT:

ServerConnection* serverConnection = [[ServerConnection alloc] init];
[LocationManager sharedLocationSingleton].delegate = serverConnection;
[[LocationManager sharedLocationSingleton] getUsersLocation];

after you comment, it is clear that the issue stems from instantiating serverConnection in a stack variable and not in a property.

Your approach of making the delegate property a strong property is not correct since it leads to retain cycles. What you need to do is defining a strong serverConnection property in the class that executes the code I pasted above (the app delegate?).

If you don't mind my being rash, if you define the delegate as a strong property, what you are doing is fixing a bug by adding a second bug that hides the first one.

Community
  • 1
  • 1
sergio
  • 68,819
  • 11
  • 102
  • 123
  • Thanks! Fixed this by changing my property declaration of the delegate from weak to strong – Rohan Agarwal Dec 21 '12 at 12:26
  • setting a delegate as a strong property is recipe for disaster, since it will cause a cyclic dependency:http://stackoverflow.com/questions/8449040/why-use-weak-pointer-for-delegation – sergio Dec 21 '12 at 12:34
-1

It looks like serverConnection is not retained anywhere and because delegate property is specified as weak, it is released and set to nil.

Check getUsersLocation method and see if delegate is nil at the moment you are trying to call LocationManagerUpdated:withValue:

Mindaugas
  • 1,707
  • 13
  • 20
  • Thanks! I fixed it by making the delegate property strong instead of weak – Rohan Agarwal Dec 21 '12 at 12:29
  • You should not make delegate property strong. I would suggest to think about other solution. The question is, why don't you retain `serverConnection` anywhere. Maybe you don't need this `delegate` property and just make `serverConnection` as private property of your `LocationManager` – Mindaugas Dec 21 '12 at 12:39