-1

FINAL SOLUTION THAT I USED: This method did not work out very well for me, and I only had 2 variables which had to be transferred so I decided to use NSNotificationCenter to send the objects. Please use this ONLY if you have very little objects to transfer, or else it could get extremely messy! If you want to learn more about this, I recommend that you check out this question: pass NSString variable to other class with NSNotification Good Luck!

I'm trying to access data from my App Delegate, but I'm always getting a (null).

EDIT: If anyone wants the full code, here it is: http://pastebin.com/hNUPMcvB

Here's the code in my AppDelegate:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    // Stop Location Services
    [locationManager stopUpdatingLocation];
    // Some Reverse Geocoding...
    CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
    [geoCoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
        for (CLPlacemark * placemark in placemarks) {
            City = [[placemark locality] stringByReplacingOccurrencesOfString:@" " withString:@"+"];
            State = [[placemark administrativeArea] stringByReplacingOccurrencesOfString:@" " withString:@"+"];
            Final = [NSString stringWithFormat:@"%@,%@", City, State];
            currentLocation = [NSString stringWithFormat:@"%@", Final];
            [self everythingelse];
            NSLog(@"AAA%@", currentLocation);
        }
    }
     ];

}

This is how I'm accessing the code from my other View Controller:

    ForecasterAppDelegate *BossMan = (ForecasterAppDelegate *)[[UIApplication sharedApplication] delegate];
    CurrentLocation = BossMan.currentLocation;
    NSLog(@"CCC%@", CurrentLocation);

It always logs as CCC(null). In my AppDelegate, it comes out right, but in the other view controller its not. I'm either making a small mistake or a huge one, any help would be great!

EDIT: Here are my header files:

My App Delegate .h:

@interface ForecasterAppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate> {
    UIStoryboard *storyboard;
    NSString *City, *State, *Final, *currentLocation;
    NSMutableString *FinalQuery;
    CLLocationManager *locationManager;
    CLPlacemark * myPlacemark;
}

@property (strong, nonatomic) UIWindow *window;
@property (nonatomic,retain) CLLocationManager *locationManager;
@property (nonatomic, retain) NSMutableString *FinalQuery;
@property (strong, nonatomic) NSString *currentLocation;
@property (nonatomic, retain) NSString *Final;

and here is my View Controller .h file:

@interface View1 : UIViewController <CLLocationManagerDelegate, LocationDamn> {
        CLLocationManager *locationManager;
        CLPlacemark * myPlacemark;
        NSString *launchpath;
        NSString *City, *State, *condition, *Final, *degreesign, *changeLocation, *currentLocations;
    }


    @property (nonatomic,retain) CLLocationManager *locationManager;
    @property (nonatomic,retain) IBOutlet UILabel *currentTempLabel, *highTempLabel, *lowTempLabel, *conditionsLabel, *cityLabel, *day2c, *day3c, *currentconditions;
    @property (nonatomic,retain) IBOutlet NSString *currentLocations;



    @end

In my viewdidload of my ViewController, I have this:

    [self performSelector:@selector(DoSomethingCool) withObject:nil afterDelay:1.5];

so that the location manager has some time to get the location.

Community
  • 1
  • 1
sridvijay
  • 1,526
  • 18
  • 39
  • 1
    what does your "`CurrentLocation`" property declaration look like in your "`.h`" file? Also, rename "`CurrentLocation`" to "`currentLocation`". Objective C naming conventions are that variable names should *never* start with capital letters. – Michael Dautermann Jul 11 '12 at 20:08
  • 3
    What's your implementation for "CurrentLocation" look like. I don't see you setting it as "self.CurrentLocation" so its possible that the value is not getting retained. If you want to expose that value to other view controllers then it needs to be retained property IMO. – jerrylroberts Jul 11 '12 at 20:08
  • What does the NSLog AAA statement return? Please provide the .h file. – Hermann Klecker Jul 11 '12 at 20:27
  • @jerrylroberts Please see the comment above to Micheal, thanks! – sridvijay Jul 11 '12 at 23:12
  • @HermannKlecker NSLog AAA returns back the currentLocation in the App Delegate, where the location is being retrieved. – sridvijay Jul 11 '12 at 23:19
  • 1
    Are you sure that the code to set currentLocation is running before the code in your view controller? i.e., are you see "AAA" in the log before "CCC"? Also, where do you declare `CurrentLocation` in your view controller? I don't see it declared in your `ViewController.h` file. – ravron Jul 11 '12 at 23:28
  • @Riley I have AAA come before CCC, and I was erasing some other code in the header file so it would be easier to read, but I accidentally deleted currentLocation as well, thanks for pointing that out. Right now I have CCC on a delay of 1 second so that I can get the location first. Is that wrong? – sridvijay Jul 11 '12 at 23:39
  • I see. Do me a favor and edit your question, adding your declaration of `currentLocation` to the code you show from your header, just so other users don't have the same question I did. No, the delay doesn't sound like a problem. Try declaring a local variable right before your `NSLog(@"CCC%@", CurrentLocation)`: `NSString *tempLoc = BossMan.currentLocation` and then `NSLog(@"CCC%@", tempLoc)`. – ravron Jul 11 '12 at 23:48
  • @Riley Thanks, updated the question, and even after the local variable, I still get the CCC(null)... – sridvijay Jul 12 '12 at 00:00

2 Answers2

2

You're not using the setter when assigning your value therefore it's not retaining the value. Try changing:

currentLocation = [NSString stringWithFormat:@"%@", Final];

To

self.currentLocation = [NSString stringWithFormat:@"%@", Final];

To avoid confusion you can stop declaring your instance variables in your headers... try this:

@interface ForecasterAppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate> 

@property (strong, nonatomic) UIWindow *window;
@property (nonatomic,retain) CLLocationManager *locationManager;
@property (nonatomic, retain) NSMutableString *FinalQuery;
@property (strong, nonatomic) NSString *currentLocation;
@property (nonatomic, retain) NSString *Final;

and add this to your implementation

@sysnthesize window=_window, locationManager=_locationManager, FinalQuery = _FinalQuery, currentLocation=_currentLocation, Final=_final;

That's the standard way and then if you try

 currentLocation = [NSString stringWithFormat:@"%@", Final];

The compiler will throw an error, which will prevent you from setting the instance variable by accident. Now, with those changes, your real issue starts to become apparent. Your code was setting the value like

_currentLocation = [NSString stringWithFormat:@"%@",Final];

This sets the instance variable directly so the value does not get retained. The value is probably getting thrown away at the next curly bracket because nothing has retained it. When you prefix it with self as self.currentLocation = some value then you are passing the value to a setter which retains. Then it should be available for all your view controllers :)

Hope this helps, if you find it confusing let me know and I'll try to edit it down a little.

jerrylroberts
  • 3,419
  • 23
  • 22
  • Just a little confusion here, so I set it to self.currentLocation, and I got the same (null) error, but I think I'm doing something a little wrong here. After I add the synthesize to my implementation, should everything in the code be_(insertobjecthere)? Thank you so much for helping, I really appreciate it! – sridvijay Jul 11 '12 at 23:57
  • Left side of the equals is the property name, right side is _propertyname. It's a convention to imply its private. Don't forget location manager is async so it will be null until it zeros in on your location – jerrylroberts Jul 12 '12 at 00:02
  • Yup, I have a delay set (edited the question) so that the location manager has time to get the location. I have no idea what you mean on it's a convention to imply its private, could you explain that a bit more? – sridvijay Jul 12 '12 at 00:03
  • Instead of setting a delay, have your app delegate post a notification with NSNotificationCenter each time it sets the location. Then have your views subscribe to that notification so that they fetch the value from the app delegate on notification – jerrylroberts Jul 12 '12 at 00:07
  • I don't why I didn't think of that, thanks! Any idea on the (null) error? Would something like a singleton work for this? I've never created one before, or is there any other way I can share this data? It's really just 2 pieces of data, a currentLocation and a custom location. Everyone says to stay away from global variables, but in this case would it really be that bad? – sridvijay Jul 12 '12 at 00:11
  • Do your header files look exactly like the code in your question, after your edits? – jerrylroberts Jul 12 '12 at 00:29
  • In the end, I decided to go with sending the object with NSNotificationCenter as I only had 2 objects to send, both at the end of methods. Thank you so much for your help, as after I was re-reading the comments and answers, when you wrote NSNotificationCenter is striked me that I could send objects with that, and it worked great! Thank you! – sridvijay Jul 12 '12 at 02:07
  • Awesome! Glad I could help, your final solution sounds pretty clean :) – jerrylroberts Jul 12 '12 at 10:38
0

It depends on where you define CurrentLocation. Since you don't get any error while accessing from the other view controller (I assumed), you defined CurrentLocation as a property in your ForecasterAppDelegate.h file. It is possible that you forgot to add retain property to the CurrentLocation. Alternatively, if you're using ARC then you can use strong as below.

@property(strong) NSString *currentLocation

fatih
  • 1,171
  • 2
  • 14
  • 26