Iam making an iphone app, which should take in latitude and longitudes from an array and should locate and display the map with a customized annotation/pins. I have used the mapkit here's how:
//MapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController <MKMapViewDelegate> {
IBOutlet MKMapView *mapView;
MKPlacemark *mPlacemark;
}
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
#end
//MapViewController.m
#import "MapViewController.h"
#import <MapKit/MapKit.h>
#implementation MapViewController
#synthesize mapView;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
CLLocationCoordinate2D location = mapView.userLocation.coordinate;
MKCoordinateRegion region;
MKCoordinateSpan span;
location.latitude = 37.250556;
location.longitude = -96.358333;
span.latitudeDelta = 0.05;
span.longitudeDelta = 0.05;
region.span = span;
region.center = location;
[mapView setRegion:region animated:YES];
[mapView regionThatFits:region];
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
[mapView setNeedsDisplay];
}
#end
This does not locate the place for the latitude and longitude. Please help.
I have made a sample project with your code and it works fine - map gets positioned to the expected (it seems) region. Check if your mapView ivar is initialized (are connections set properly in IB?)
Edit: In your code you just set map's visible region but do not add any annotations to it (apart from automatically showing current user position which is always in Cupertino if you test on simulator). To put pin to you map you need to create an object confirming to MKAnnotation protocol and add it to mapView:
// Sample example just to show annotation
// in your program you will likely need to use custom annotation objects
CLLocation* myLocation = [[CLLocation alloc] initWithLatitude:37.250556 longitude:-96.358333];
[mapView addAnnotation:myLocation];
Some (not so relevant) comments on your code:
You don't need to initialize location variable with current location as you overwrite its coordinate values immediately after that
Why do you call [mapView setNeedsDisplay]; in viewDidUnload method? I'm not sure if this may cause serious problems but you must use this method for cleaning memory up (e.g. releasing retained outlets), not for redrawing your UI
Have you set your map to follow user location somewhere else? maybe that default is overruling your manual movement of the map to Kansas.
edit
Do'h, didn't see this was July last year. Well maybe you could share your solution with us if this wasn't the problem
Related
I have already add UIViewController<MKMapViewDelegate> in .h and already add
-(void) viewDidLoad {
self.mapView.delegate = self;
}
but the method viewForAnnotation never called
MapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface Tela1ViewController : UIViewController<MKMapViewDelegate> {
IBOutlet MKMapView *mapView;
}
#property (nonatomic, retain) MKMapView *mapView;
#end
MapViewController.m
-(void) viewDidLoad {
self.mapView.delegate = self;
}
- (void)viewDidAppear:(BOOL)animated
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication shared
mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
mapView.mapType = MKMapTypeSatellite;
CLLocationCoordinate2D coord = {latitude: appDelegate.latitude, longitude: appDelegate.longitude};
MKCoordinateSpan span = {latitudeDelta:0.2, longitudeDelta: 0.2};
MKCoordinateRegion region = {coord, span};
[mapView setRegion:region];
PlaceMark *addAnnotation = [[PlaceMark alloc] initWithCoordinate:coord];
[mapView addAnnotation:addAnnotation];
[self.view addSubview:mapView];
}
- (MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation
{
NSLog(#"test");
}
Okay, couple of things to fix in your code ...
Delegate of MKMapView
Is nil. Why? Because you set delegate of MKMapView in viewDidLoad method. But when you look at viewDidAppear:, you're allocating new MKMapView and you're not setting delegate there. And because viewDidLoad is called before viewDidAppear:, delegate is simply nil = not set.
Calling super
When you override some methods, read documentation. Because you can find this in viewDidAppear: documentation for example:
You can override this method to perform additional tasks associated with presenting the view. If you override this method, you must call super at some point in your implementation.
MKMapView & IBOutlet
And also don't understand why do you have MKMapView as IBOutlet and then you're allocating new MKMapView and adding it as subview. Also if your IBOutlet is really connected to a MKMapView in your XIB, you'll end up with two MKMapViews, because the old one (from XIB) is not removed from superview.
You're clearly messing things up. Go and read more about UIKit, ...
Try replacing the last several lines of you viewDidAppear method with the following:
CLLocationCoordinate2D coord = {.latitude = location.latitude, .longitude = location.longitude};
MKCoordinateSpan span = {.latitudeDelta = 0.2, .longitudeDelta = 0.2};
MKCoordinateRegion region = {coord, span};
[mapView setRegion:region];
MapAnnotation *addAnnotation = [[MapAnnotation alloc] initWithCoordinate:coord];
[mapView addAnnotation:addAnnotation];
[self.view addSubview:mapView];
I am completely new to iOS development so I may be doing this wrong but I have a class I am using to get coordinate gps data that I want to have as a generic class I can reuse in lots of apps. My problem is getting the data from the gps to properly display in other apps.
Here is my header file for the GPS class:
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface LocationAwareness : NSObject <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
}
#property(copy) NSString *longitude;
#property(copy) NSString *latitude;
#end
And here is the implementation:
#import "LocationAwareness.h"
#implementation LocationAwareness
#synthesize longitude;
#synthesize latitude;
- (id)init {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
return self;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// Stops updating location if data has been updated within 10 minutes
if ( abs([newLocation.timestamp timeIntervalSinceDate: [NSDate date]]) < 600) {
[locationManager stopUpdatingLocation];
float latitudedata = newLocation.coordinate.latitude;
latitude = [NSString stringWithFormat:#"%f", latitudedata];
float logitudedata = newLocation.coordinate.longitude;
longitude = [NSString stringWithFormat:#"%f", logitudedata];
}
}
#end
Now I can't seem to find anywhere that tells me how to get the latitude or longitude properties in another project. I have the header imported and have tried to store LocationAwareness.latitude into a variable that I can use but everything I store it in ends up blank. When I start my main class and aloc init a locationawareness object the gps fires up so I think its working but I don't seem to know enough about how this works to get everything in order. I've been searching the internet for hours. Anyone have an idea what I am doing wrong?
Well, this may or may not be causing the problem (it's quite likely), but a major problem is your init method.
The beginning should be:
self = [super init];
if (self) {
// Do your initializing as you did above.
}
return self;
edit:
I added your code with my update to a project and it works well.
In order to use this, you should do something like the following:
LocationAwareness *loc = [[LocationAwareness alloc] init];
// Give it some time to start updating the current location and then
// in a different function:
NSLog(#"%#", loc.latitude);
EDIT 2
Wherever you are using this, you will want to declare a property which stores it so that you can create it once and reference it many times. To do that, use the following code:
In the header for the object where you want to use this object, add this with the other properties:
#property (nonatomic, assign) LocationAwareness *location;
Then, towards the top of your implementation file (.m file) you should see other #synthesize lines, add this one:
#synthesize location;
Then, create the actual location instance that you want to use as per the example above:
self.location = [[LocationAwareness alloc] init];
Now give it some time to figure out your location and start providing updates. Then you can print the location like this:
NSLog(#"%#", self.location.latitude);
I was wondering how I would add pins to a MapView within an iPhone app. I want to have pins pinned in places that have the word "Tea" in their name and it would be impractical to place each pin in every place that contains that word, so I was wondering if there's some way to make it so that when the MapView is loaded, the pins are pinned into those places. I assume that this would be done with Google's Map API however I'm unsure as to how I'd exactly do this - does anyone know of any tutorials that would show to implement this.
So far, I have a simple view that contains a MapView as well as a corresponding view controller.
Thanks in advance!
You'll have to add instances of MKAnnotation to your MKMapView.
[mapView addAnnotation:annotation];
annotation is an instance of a class conforming to the MKAnnotation protocol. Read the corresponding documentation here:
http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKMapView_Class/MKMapView/MKMapView.html
http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKAnnotation_Protocol/Reference/Reference.html#//apple_ref/occ/intf/MKAnnotation
Sample code:
#interface MyAnnotation: NSObject <MKAnnotation>
{
CLLocationCoordinate2D coordinate;
NSString *title;
}
#end
#implementation MyAnnotation
#synthesize coordinate, title;
- (id) init
{
if ((self = [super init]))
{
coordinate.latitude = 0.0;
coordinate.longitude = 0.0;
title = NSLocalizedString(#"Tea");
}
return self;
}
#end
In your view controller:
- (void) viewDidLoad
{
[super viewDidLoad];
// custom initialiation; create map view
[self addPin]; // or with parameters, called multiple times, to add several annotations
}
- (void) addPin
{
MyAnnotation *ann = [[MyAnnotation alloc] init];
[mapView addAnnotation:ann];
[ann release];
}
Hope this helps.
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
I need to read my position from GPS!
The problem is that i need to do out from the method
- (void)locationUpdate:(CLLocation *)location;
So... this is how i'm working:
in the .h file i have this
CLLocation *mylocation;
in the -viewDidLoad
mylocation = [[CLLocation alloc] init];
locationController = [[CLController alloc] init];
locationController.delegate = self;
[locationController.locationManager startUpdatingLocation];
then
- (void)locationUpdate:(CLLocation *)location {
mylocation = location;
}
and it works, if i use NSLog (on mylocation) i see my real location!
But... in another method (an IBAction connected with a UIButton) i want to use "mylocation"!
It's not working and i don't know why!
If, in this method, i try to do this
NSLog(#"%#", mylocation);
the console report this:
<+0.00000000, +0.00000000> +/- 0.00m (speed -1.00 mps / course -1.00) # 3/10/11 7:21:24 PM Central European Time
So the variable is empty!
Why??
PS= also in my IBAction i have, of course, this
mylocation = [[LCLocation alloc] init];
otherwise the app crashes!
This line:
mylocation = location;
Is setting mylocation's memory pointer to the one returned by the location manager, which later is getting released.
EDITED:
mylocation = [[CLLocation alloc] initWithLatitude:location.coordinate.latitude longitude:location.coordinate.longitude];
also in my IBAction i have, of course, this
mylocation = [[LCLocation alloc] init];
So you get zero values because you always overwrite your location value with newly created blank location - you should not do that.
The problem that makes your application crash is that in locationUpdate method you get autoreleased value, so in order to ensure that its valid outside of that method you must retain it. (and not forget to release old value). The easiest way to do that is create a property for myLocation ivar and access ivar using it:
// .h file
#property (nonatomic, retain) CLLocation *myLocation;
// .m
#synthesize myLocation;
...
- (void)locationUpdate:(CLLocation *)location {
self.mylocation = location;
}
- (void) dealloc{
[myLocation release];
myLocation = nil;
...
[super dealloc];
}