2

I have an Xcode project which basically loads and parses a xml file which outputs a list a list of locations (venues) close to the users current location. I originally hard-coded the longitude and latitude co-ordinates to ensure my xml was parsing correctly (which it is), but now i'm attempting to pass the users current location to determine the closest locations to the user (similar to a store finder). I have a delegate class file which handles loading the xml file and a rootViewController file which handles the users current location. My issue is that i don't know the best way to pass the parameters from one class to a delegate class... Sorry i know it's basic but i'm struggling with it :)

Here two snippets of the basis of what i have:

RootViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];

    // Get Current Location
    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
    locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
    [locationManager startUpdatingLocation];

    appDelegate = (XMLAppDelegate *)[[UIApplication sharedApplication] delegate];

}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    int degrees = newLocation.coordinate.latitude;
    double decimal = fabs(newLocation.coordinate.latitude - degrees);
    int minutes = decimal * 60;
    double seconds = decimal * 3600 - minutes * 60;
    NSString *lat = [NSString stringWithFormat:@"%d° %d' %1.4f\"", degrees, minutes, seconds];

    degrees = newLocation.coordinate.longitude;
    decimal = fabs(newLocation.coordinate.longitude - degrees);
    minutes = decimal * 60;
    seconds = decimal * 3600 - minutes * 60;
    NSString *longt = [NSString stringWithFormat:@"%d° %d' %1.4f\"", degrees, minutes, seconds];

    NSLog(@"longt Value: %@", longt);
}

XMLAppDelegate.m

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    //This code is incorrect (displays 'null') I want to display the values defined in the locationManager Method on RootViewController.m
    NSLog(@"lat Value: %@", currentLocation.coordinate.latitude);

    // Longitude and Latitude codes are hard-coded. I want to change this to dynamic values which are defined in the locationManager Method on RootViewController.m
    NSURL *url = [[NSURL alloc] initWithString:@"http://www.domain.com/phpsqlsearch_genxml.php?lat=-33.870017&lng=151.206547&radius=25"];

    //More code here....
}

I'm able to display the results (NSLog) on the RootViewController.m file but not on the XMLAppDelegate.m file. I need to find out the best way to pass the parameters to the from RootViewController.m to XMLAppDelegate.m?

Please let me know if there is anymore information you require.

Cheers

4
  • 3
    applicationDidFinishLaunching is the first thing that will be called, viewDidLoad will happen after it, so the changes made there won't have any effect on appDidFinishLaunching Commented Dec 14, 2011 at 2:50
  • You should use the objects/values of appDelegate in other class, not vice versa. Commented Dec 14, 2011 at 3:17
  • Also, currentLocation.coordinate.latitude is a number (integer or float). You're lucky you got (null) as if it hadn't been 0, the NSLog would have tried to access it as an NSObject and would have crashed. You should use the appropriate format specifier ("%d" for integers, "%f" for floats) in NSLog. Commented Dec 14, 2011 at 16:01
  • Cheers for your responses, i have some work to do - but thank your for pointing me in the right direction! Commented Dec 15, 2011 at 23:23

2 Answers 2

1

I would say, do it like Apple is doing it. Let say we take the UITableView as an example.

First, the delegate is the object that will help an other class, you should think of delegate as helper class, (I know this is not entirely true).
So in the UITableView case, the UITableView is asking it's delegate to do some work, and since it is asking it is listening for the return to.
When you get this call from a UITableView

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 

You are sending back information to the master of the delegate about how much sections there should be in the UITableView.

Second, if you look closely to the method signature you will see that the master is passing itself as a parameter, so the delegate can ask it's master for some more information if needed.

So this is how this work, the master have a pointer to it's delegate to be able to ask it some question, and the delegate get to know it's master when it get call. The delegate can store a pointer to it's master, but as you see it is not necessary.

Which mean that you always have a reference to delegate or to master and if you have a reference to it, sending information is not a problem.

And remember that the delegate should be the one that provide the information to it's master, so if I read correctly your code you are doing the inverse.

Sign up to request clarification or add additional context in comments.

Comments

1

Your classes would look something like this with the ability to communicate with one another:

RootViewController.h:

#import <Foundation/Foundation.h>
#import <CoreLoation/CoreLocation.h>
#import <UIKit/UIKit.h>
#import "XMLAppDelegate.h"

@interface RootViewController: UIViewController <CLLocationManagerDelegate, CustomDelegateProtocol> {
    float lon, lat;
}

@end

RootViewController.m:

#import "RootViewController.h"

@implementation RootViewController

// super

- (void)viewDidLoad {
    [super viewDidLoad];

    // Get Current Location
    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
    locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
    [locationManager startUpdatingLocation];

    appDelegate = (XMLAppDelegate *)[[UIApplication sharedApplication] delegate];

}

// CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    int degrees = newLocation.coordinate.latitude;
    double decimal = fabs(newLocation.coordinate.latitude - degrees);
    int minutes = decimal * 60;
    double seconds = decimal * 3600 - minutes * 60;
    NSString *lat = [NSString stringWithFormat:@"%d° %d' %1.4f\"", degrees, minutes, seconds];

    degrees = newLocation.coordinate.longitude;
    decimal = fabs(newLocation.coordinate.longitude - degrees);
    minutes = decimal * 60;
    seconds = decimal * 3600 - minutes * 60;
    NSString *longt = [NSString stringWithFormat:@"%d° %d' %1.4f\"", degrees, minutes, seconds];

    NSLog(@"longt Value: %@", longt);
}

// CustomDelegateProtocol

@synthesize lon = lon, lat = lat;

@end

XMLAppDelegate.h:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@protocol CustomDelegateProtocol

@property (assign) float lon;
@property (assign) float lat;

@end

@interface XMLAppDelegate: NSObject <UIApplicationDelegate> {
    // whatever instance variables you need, put them here
    id <CustomDelegateProtocol> delegate;
}

@end

XMLAppDelegate.m:

#import "XMLAppDelegate.h"

@implementation XMLAppDelegate

/*
- (void)applicationDidFinishLaunching:(UIApplication *)application {
    // BTW: don't use this to obtain location info if you're NOT setting up your UI from code...
    // It has (conceptually, but also practically) be done in your view controller.
    // That's why it is called a view controller: it "glues" view and logic code together
    // and that way you won't even need the delegate
    // I also recommend using the -application:didFinishLaunchingWithOptions: method. This one is deprecated.
}
*/

- (BOOL) application:(UIApplication *)app didFinishLaunhingWithOptions:(NSDictionary *)launchOpts {
    // set up initial stuff, etc...
    // and if you *really, badly* want to use the delegation model, here you are:
    NSString *urlString = [[NSString alloc] initWithFormat: @"http://www.domain.com/phpsqlsearch_genxml.php?lat=-%f&lng=%f&radius=25", self.delegate.lat, self.delegate.lon];
    NSURL *url = [[NSURL alloc] initWithString:urlString];
    [urlString release];

    // do whatever you want to 


    return YES;
}

@end

Hope this helps.

1 Comment

Both excellent responses! Thankyou both for your help on this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.