Why is didFindPlacemark never hit? - iphone

I am struggling with getting my MKReverseGeocoder to actually finish. This is what I do:
// reverse geocode the user location
geocoder = [[[MKReverseGeocoder alloc] initWithCoordinate:mapView.userLocation.location.coordinate] autorelease];
geocoder.delegate = self;
[geocoder start];
The userLocation coordinate IS valid, I know that. I have didFindPlacemark and didFailWithError, and neither of those are hit...
Either I have the delegate set up wrong or I have no idea...Here's the header:
#interface E_85AppDelegate : UIViewController <UIApplicationDelegate, MKMapViewDelegate, MKReverseGeocoderDelegate, CLLocationManagerDelegate>
{
IBOutlet UIWindow *window;
IBOutlet UITabBarController* tabBarController;
IBOutlet MKMapView* mapView;
IBOutlet MKReverseGeocoder* geocoder;
// other class members...
}
Any ideas?

Evidently my understanding of autorelease is not very good. It releases the geocoder before didFindPlacemark is ever sent the message.

Related

Distance between CLLocations won't return correctly

In my app, I'm trying to get the distance between two locations. I pressed my app's button, walked across the (big) room, and the CLLocationDistance returned as 0.000000.
.h file:
#property (strong, nonatomic) IBOutlet UIImageView *stopButton;
#property (strong, nonatomic) CLLocationManager *locationManager;
#property (strong, nonatomic) CLLocation *firstLocation;
#property (strong, nonatomic) CLLocation *secondLocation;
#property (strong, nonatomic) IBOutlet UILabel *locationLabel;
.m file:
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
self.firstLocation = [self deviceLocation];
}
- myButtonFunction {
self.secondLocation = [self deviceLocation];
self.locationLabel.text = [[NSString alloc] initWithFormat:#"%f", [self.firstLocation distanceFromLocation:self.secondLocation]];
}
- (CLLocation *)deviceLocation {
return [[CLLocation alloc] initWithLatitude:self.locationManager.location.coordinate.latitude longitude:self.locationManager.location.coordinate.longitude];
}
You need to wait until the location manager tells you that it has new information. Until that happens, you'll just get the same location all the time.
The manager will inform you via the delegate method locationManager:didUpdateLocations: (locationManager:didUpdateToLocation:fromLocation: for iOS < 6.0). You need a class that implements that method to be assigned as the location manager's delegate, and you can't check the new location until that method is called.
Also, be aware that the first time that method is called, there might not actually be fresh data. See my answer at "Core Location Negative Values".
By using the device location you lose a lot of control over what is actually being recorded. For example, the device location could have conditions where it does not update unless your location changes by more than 20 meters... Or perhaps it updates once an hour. You have no way to know.
As Josh was saying you have to get locations from the CLLocationManagerDelegate callback(s). Store them in your class, and when your buttons are hit record the last location you stored. Only then will you get data related to the location settings you have specified.

tabbarcontroller and facebook api

I'm trying to implement Facebook API in my app code.
Pratically i have a simple TabbarController with 2 ViewController.
My AppDelegate code:
#interface AppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
UIWindow *window;
UITabBarController *tabBarController;
Facebook *facebook;
}
#property (retain, nonatomic) IBOutlet UIWindow *window;
#property (retain, nonatomic) IBOutlet UITabBarController *tabBarController;
#property (retain, nonatomic) Facebook *facebook;
method code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self.window addSubview:self.tabBarController.view];
[self.window makeKeyAndVisible];
facebook = [[Facebook alloc] initWithAppId:#"12345678910" andDelegate:_tabBarController];
............
return YES;
}
FirstViewController.h
#import "Facebook.h"
#interface FirstViewController : UIViewController <FBRequestDelegate, FBDialogDelegate, FBSessionDelegate> {
}
FirstViewController.m
#import "Appdelegate.h"
-(IBAction)shareFacebook {
AppDelegate *appdelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if (![appdelegate.facebook isSessionValid]) {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"publish_stream",
#"read_stream",
nil];
[appdelegate.facebook authorize:permissions];
[permissions release];
}
}
I received a warning for this code: "andDelegate:_tabBarController"
Sending "UITabBarController *" to parameter of incompatible type 'id'
i would say UITabBarController * is not an FBSessionDelegate ... add the protocol as <UIApplicationDelegate, UITabBarControllerDelegate,FBSessionDelegate > and then
facebook = [[Facebook alloc] initWithAppId:#"12345678910" andDelegate:self];
In my app I declare and initialize the facebook object in the AppDelegate just like you. However, I made the AppDelegate use these (just like the other answer said it) : FBRequestDelegate, FBDialogDelegate, FBSessionDelegate. After that I placed all the facebook login/logout/post..etc methods in app delegate class.
After that you can just pass the facebook object to your FirstViewController from the didFinishLaunchingWithOptions.
If you dont understand let me know I'll give you more details. I might not explain it very well.
PS: i might be wrong with this but from what i've seen around the web it is easier to declare methods at the beginning in the app delagete didfinishlaunchingwithoptions and then pass them to specific view controllers.

How can I integrate core location data to my blank iPhone App without introducing View or tab controller?

How can I integrate core location data (Lat, Long, Altitude) into my (single view) iPhone app without creating additional view controllers or tab controllers? in other words, when I run the app I want to see a blank screen (xView) but be able to collect (Longitude, Latitude information in the background and then maybe store the coordinates in a file or pass it on to a other functions. Sorry if this sounds like a dumb question. I am new to iOS development. Thanks.
HelloXYZAppDelegate.h:
#import <UIKit/UIkit.h>
#import "MyclassView.h"
#interface HelloXYZAppDelegate: NSObject <UIApplicationDelegate>
{
MyClassView* _xView;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet MyClassView *xView;
#end
HelloXYZAppDelegate.m
#import "HelloXYZAppDelegate.h"
#implementation HelloXYZAppDelegate
#synthesize xView=_xView;
#synthesize window=_window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
{
self.xView = [[[MyClassView alloc] initWithFrame:screenBounds] autorelease];
[self.window addSubview:_xView];
[self.window makeKeyAndVisible];
return YES;
}
#end
MyClassView.h:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#include <OpenGLES/ES2/gl.h>
#interface MyClassView : UIView
{
CAEAGLLayer* _eaglLayer;
EAGLContext* _context;
GLuint _CRBuffer;
GLuint _PSlot;
....
....
....
CLLocationManager *LM; //not sure if I can do this in here
CLLocation *SP; //not sure if I can do this in here
}
#property (nonatomic, retain) CLLocationManager *LM;
#property (nonatomic, retain) CLLocation *SP;
#end
MyClassView.m
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
if (SP == nil)
self.SP = newLocation;
NSString *latitudeString = [[NSString alloc] initWithFormat:#"%g\u00B0",
newLocation.coordinate.latitude];
NSLog(#"latitude is %#", latitudeString);
[latitudeString release];
}
- (void)viewDidLoad
{
self.LM = [[CLLocationManager alloc] init];
LM.delegate = self;
LM.desiredAccuracy = kCLLocationAccuracyBest;
[LM startUpdatingLocation];
[super viewDidLoad];
}
very simple tutorial on core location. If you're looking to store the data for use later on you'll either want to make a data NSObject class, but seeing as you dont want to make extra classed, define two #property NSStrings lat and long, when the location is created set the two strings to the two variables and you can access them later.
The tutorial prints the data on the screen, just leave that part out if you dont want it

#synthesize interferes with inheritance

FINAL EDIT
The solution to all life's problems:
Switching xcode's "Compiler Version" setting to "LLVM compiler 2.0" solves this issue, many thanks to Firoze Lafeer for the concerted, constructive assistance!
Intention was to build some really basic functionality into all my classes by subclassing NSObject and UIViewController with something to grab the application delegate, extend the viewDidAppear mechanism a little, etc. I've got a base class that looks something like this (only relevant lines included):
#interface PHView : UIViewController {
id<PHAppDelegate> appDelegate;
}
-(id)init;
//some other method prototypes
#property (nonatomic, retain) id delegate;
#end
#implementation PHView
#synthesize delegate;
-(id)init {
self = [super init];
appDelegate = (id<PHAppDelegate>)[[UIApplication sharedApplication] delegate];
visible = FALSE;
initialized = FALSE;
return self;
}
//some other methods
#end
EDIT I should mention here that the property "delegate" isn't meant to point to ivar "appDelegate" or anything... I only left it in to illustrate that this superclass uses #synthesize. Since it's not a related useage I think it doesn't matter, but I wouldn't say that I know that.
Interface for the subclass:
#interface PinMap : PHView <MKMapViewDelegate> {
//#interface PinMap : UIViewController <MKMapViewDelegate> {
// NSObject<PHAppDelegate>* appDelegate;
}
-(id)init;
-(void)zoomToUser;
#property (nonatomic, retain) IBOutlet MKMapView* map;
#end
This compiles:
#implementation PinMap
//#synthesize map;
-(PinMap*) init{
self = [super init];
//appDelegate = (NSObject<PHAppDelegate>*)[[UIApplication sharedApplication] delegate];
return self;
}
-(void)zoomToUser {
//MKCoordinateRegion region = map.region;
MKCoordinateRegion region = MKCoordinateRegionMake(CLLocationCoordinate2DMake((CLLocationDegrees)300, (CLLocationDegrees)300), MKCoordinateSpanMake((CLLocationDegrees)20,(CLLocationDegrees)20)); //random region
region.center = [[appDelegate location] coordinate];
region.span.longitudeDelta /= 50.0;
region.span.latitudeDelta /= 50.0;
// [map setRegion:region animated:NO];
}
This does not compile:
#implementation PinMap
#synthesize map;
-(PinMap*) init{
self = [super init];
//appDelegate = (NSObject<PHAppDelegate>*)[[UIApplication sharedApplication] delegate];
return self;
}
-(void)zoomToUser {
MKCoordinateRegion region = map.region;
//MKCoordinateRegion region = MKCoordinateRegionMake(CLLocationCoordinate2DMake((CLLocationDegrees)300, (CLLocationDegrees)300), MKCoordinateSpanMake((CLLocationDegrees)20,(CLLocationDegrees)20)); //random region
region.center = [[appDelegate location] coordinate]; // <-- ERROR HERE
region.span.longitudeDelta /= 50.0;
region.span.latitudeDelta /= 50.0;
[map setRegion:region animated:NO];
}
At the marked location, I get """'appDelegate' undeclared (first use in this function)""" My first step was to Clean, reboot and Clean again (fixed three bugs this week using that procedure) and when that didn't work I started trying things that make sense, and eventually some things that DON'T make sense.
The following DOES compile (and run) but I honestly don't understand why:
#interface PinMap : PHView <MKMapViewDelegate> {
//#interface PinMap : UIViewController <MKMapViewDelegate> {
//NSObject<PHAppDelegate>* appDelegate;
MKMapView* _map;
}
-(id)init;
-(void)zoomToUser;
#property (nonatomic, retain) IBOutlet MKMapView* map;
#end
#implementation PinMap
#synthesize map=_map;
-(PinMap*) init{
self = [super init];
//appDelegate = (NSObject<PHAppDelegate>*)[[UIApplication sharedApplication] delegate];
return self;
}
-(void)zoomToUser {
MKCoordinateRegion region = self.map.region;
//MKCoordinateRegion region = MKCoordinateRegionMake(CLLocationCoordinate2DMake((CLLocationDegrees)300, (CLLocationDegrees)300), MKCoordinateSpanMake((CLLocationDegrees)20,(CLLocationDegrees)20)); //random region
region.center = [[appDelegate location] coordinate];
region.span.longitudeDelta /= 50.0;
region.span.latitudeDelta /= 50.0;
[self.map setRegion:region animated:NO];
}
In this trim it'll respond to "self.map" but considers "map" to be undeclared.
EDIT The "self" requirement makes sense to me now, but the disappearing / reappearing "appDelegate" ivar is what I'm actually worried about. Sorry if that was unclear before. But seriously, what's up with that?
Well, for starters, PinMap doesn't have an instance variable (ivar) called 'map'.
It has a property called 'map', which you can access like so:
region = self.map.region;
Or it has an ivar called _map. So you could do this:
region = _map.region;
But the former is recommended. You made a property, so you probably want to use it (outside of initXXX and dealloc)
EDIT
Also, the designated initializer for UIViewController is initWithNibName:bundle:
So just make sure if you subclass UIViewController that you call its designated initializer.
EDIT AGAIN
In those cases in your comment, you probably have an ivar and a property with the same name. If you just do #synthesize propname, that's what you get. But in this case you did #synthesize map = _map.
It's worth taking the time to understand when you are accessing the ivar directly, versus the property. Otherwise a lot of things won't make sense, and other bugs will happen. To access the property you must do 'self.propertyName' (or [self propertyName] or [self setPropertyName:something])
If you aren't using self, you aren't using the getter/setter (this is often a bad thing, if for example your getter/setter is doing your memory mgmt or initialization for you). You also have to use the actual ivar name if you aren't going to use the property.
EDIT AGAIN AGAIN
I see changing the compiler helped. I would suggest two things then: double check all of your #synthesize statements to make sure you aren't asking the compiler to synthesize an ivar in a subclass that already exists in a superclass. While you're sorting that out, I would recommend you name your ivars as variable_ or _variable so you can easily see where you are using the ivar versus the property.
And more importantly, you should really upgrade to LLVM 3.0, which is included in Xcode 4.2.1.
#synthesize creates the setter and getter methods for a property, however it needs some place to store that object so you must add some sort of ivar to use #synthesize with a property
you can do
#interface ... : ... {
Something* smth;
}
#property (nonatomic, retain) Something *smth;
#end
#implementation ...
#synthesize smth;
#end
or
#interface ... : ... {
Something* _smth;
}
#property (nonatomic, retain) Something *smth;
#end
#implementation ...
#synthesize smth=_smth;
#end

Warning from AppDelegate

I am getting the following warning when I am calling other view controllers..
WindowMultivewAppDelegate might not respond to -switchView to view
This is my code in the Firstviewcontroller.m
- (IBAction)swapViews:(id)sender{
WindowMultiViewAppDelegate *delegate = (WindowMultiViewAppDelegate *)[[UIApplication sharedApplication] delegate];
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[delegate switchView:self toView:secondView.view];
}
this is my code in the Firstviewcontroller.h
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController {
}
- (IBAction)swapViews:(id)sender;
#end
in the appdelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
initWithNibName:#"FirstViewController" bundle:nil];
[self.window addSubview:navigationController.view];
locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
if ([CLLocationManager locationServicesEnabled]) {
[locationManager startUpdatingLocation];
}
[self.window makeKeyAndVisible];
return YES;
}
in the appdelegate.h
#interface WindowMultiViewAppDelegate : NSObject <UIApplicationDelegate, CLLocationManagerDelegate , MKMapViewDelegate> {
UIWindow *window;
UINavigationController *navigationController;
CLLocationManager *locationManager;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet CLLocationManager *locationManager;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
I have placed a UInavgationcontroller into the mainWindow.xib which leads to the rootviewcontroller which i named FirstViewController
The application quites in the secondviewcontroller when a button next is pressed which has that action inside
- (IBAction)swapNext:(id)sender
{
WindowMultiViewAppDelegate *delegate = (WindowMultiViewAppDelegate *)[[UIApplication sharedApplication] delegate];
MediaViewController *mediaView = [[MediaViewController alloc] initWithNibName:#"MediaViewController" bundle:nil];
[delegate switchView:self toView:mediaView.view];
}
What am I doing wrong??
Can anybody tell me how to connect more subviews into the UINavigationController
I want one of this subviews to be a video player - offline- and the other one to be a map which find the user"s location
I am a beginner.... thank you all when I learn I am going to help others :))
I don't see that you define the switchView: method anywhere, so it's no surprise that you get a warning about this.