MKMapView Annotation Callout Button to DetailView? - iphone

I have annotations in a MKMapView with Callouts. In this Callouts there's a "Right-Arrow" Button. When clicking on it, I want to open a Detail View, an extra UIViewController with its own nib file etc. I use following code:
In my MapViewController:
- (void)showDetails:(id)sender {
// the detail view does not want a toolbar so hide it
[self.navigationController setToolbarHidden:YES animated:NO];
NSLog(#"pressed!");
[self.navigationController pushViewController:self.detailViewController animated:YES];
NSLog(#"pressed --- 2!");
}
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(Annotation *) annotation {
if(annotation == map.userLocation) return nil;
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView* customPinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
customPinView.pinColor = MKPinAnnotationColorRed;
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
customPinView.rightCalloutAccessoryView = rightButton;
UIImageView *memorialIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"googlemaps_pin.png"]];
customPinView.leftCalloutAccessoryView = memorialIcon;
[memorialIcon release];
return customPinView;
}
The button works, because when I give a NSLog inside the showDetais method, it's printed to the console. The problem is, that NOTHING happens. When clicking the button, it's like there isn't any button. There's no debug error or exception, just nothing.
the MapView header looks something like this:
#interface MapViewController : UIViewController <MKMapViewDelegate> {
MKMapView *map;
NSMutableDictionary *dictionary;
EntryDetailController *detailViewController;
}
#property (nonatomic,retain) IBOutlet MKMapView *map;
#property (nonatomic,retain) IBOutlet EntryDetailController *detailViewController;
Maybe someone of you can help me :)
Thanks!

Check if you have navigation controller for your viewController, if it is just a viewController then it cannot push a viewController because it does not have navigation controller in it.

I've had the same problem in the past and so I just used a different code to switch views:
-(IBAction)showDetails:(id)sender
{
NSLog(#"button clicked");
MapViewController *thisMap = (MapViewController *)[[UIApplication sharedApplication] delegate];
detailViewController *detailView = [[detailViewController alloc]initWithNibName:#"detailViewController" bundle:nil];
[thisMap switchViews:self.view toView:dvc.view];
}
It's a pretty basic view switching method and it works fine for me.

Isn't detailViewController uninitialized? You don't show all your code but I believe you might have things a bit jumbled up preparing the view and pushing it.
Why are you declaring the detailViewController as an IBOUTlet?
Also, I think you might want/intend to do this on your detailViewController not in this controller:
[self.navigationController setToolbarHidden:YES animated:NO];

You don't show all your code. But i guess, you just forget to initialise self.detailViewController.
try to add this in your viewDidLoad method:
self.detailViewController = [[[DetailViewController alloc]init]autorelease];

Related

can not setimage of uiimageview while pushing viewcontroller

I am new on objective c and I am trying to set image of UIImageview while pushing viewcontroller
I checked other answer and I did the same way they said it but its not working for me below is my code and i will explain other things in it
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *svController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:[NSBundle mainBundle]];
UIImage *image = [UIImage imageNamed:#"default.png"];
UIImageView* imageview = [[UIImageView alloc] initWithImage:image];
id obj = [[mainArray valueForKey:#"image"] objectAtIndex:[indexPath row]];
if ([obj isKindOfClass:[NSString class]])
{
NSLog(#" image%#",image); //print this image<UIImage: 0xaa70700>
NSLog(#" image%#",svController.image); //print this image(null)
[[svController image] setImage: image];
NSLog(#" image%#",svController.image); //print this image(null)
}
else {
NSLog(#" image%#",svController.image);
[[svController image] setImage: [[mainArray valueForKey:#"image"] objectAtIndex:[indexPath row]]];
NSLog(#" image%#",svController.image);
}
[self.navigationController pushViewController:svController animated:YES];
[svController release];
svController = nil;
}
below is my detailviewcontroller
#interface DetailViewController : UIViewController{
UIImageView *image;
}
#property (retain, nonatomic) IBOutlet UIImageView *image;
its connected to Xib and i have synthesized it
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
name.text = nameString;
email.text = emailString;
NSLog(#"%#",image); // print this <UIImageView: 0x9d73950; frame = (27 35; 204 181); autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x9db4050>>
}
its working perfectly when i send NSString and set them on my lable but not working for image it its so small thing but now i dont know what to do please help
hear is the simple way, i am showing the example that u can set image in detail view controller
in your master view controller
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == 0)//for 1st row
{
DetailViewController *detController = [[DetailViewController alloc]initWithNibName:#"DetailViewController" bundle:nil];
detController.detailImage = [UIImage imageNamed:#"abc.png"];//setting the property for image
[self.navigationController pushViewController:detController animated:YES];
[detController release];//im doing without ARC
}
else if (indexPath.row == 1)
{
DetailViewController *detController = [[DetailViewController alloc]initWithNibName:#"DetailViewController" bundle:nil];
detController.detailImage = [UIImage imageNamed:#"123.png"];
[self.navigationController pushViewController:detController animated:YES];
[detController release];//im doing without ARC
}
}
and in your detail view controller
// .h file
#interface DetailViewController : UIViewController
{
}
#property (retain, nonatomic) IBOutlet UIImageView *ImageView;
#property (nonatomic, retain)UIImage * detailImage;//set a property for image that u are passing from master viewcontroller
#end
//in .m file
#implementation DetailViewController
#synthesize detailImage; //synthesise it
// and in viewDidload method
- (void)viewDidLoad
{
[super viewDidLoad];
//set your passed image to image view
self.ImageView.image = self.detailImage;
}
Better would be just do like this:
[self.navigationController pushViewController:svController animated:YES];
if(yourImage) //got UIImage reference then only set it
svController.yourImgView.image = yourImageHere
.................
<<Another code here>>
..............
Thats it....
You can't do this, because svController's view has not been loaded at the time you try to set the image of its image view (so the image view will be null).
You need to pass the image itself to a property you create in svController, and set the image in svController's viewDidLoad method.
Set your UI object intialization afer pushing view controller.
[self.navigationController pushViewController:svController animated:YES];
//set image here
Reason is viewDidLoad of svController will not be called and loaded yet and imageview will not have reference yet.
EDIT :
Better would be just do like this:
[self.navigationController pushViewController:svController animated:YES];
if(yourImage) //got UIImage reference then only set it
svController.yourImgView.image = yourImageHere
.................
<<Another code here>>
..............
Thats it....

Show another View Controller from an annotation callout button in MKMapKit

I am making an app that will use the MKMapKit for the pins and annotations. I want to display more information besides some text, so I created a button in the callout so I could make that go to another view controller. At the moment, the button in the callout doesn't do anything, as there is no code to make it work. It would be great if someone could make the code for the button to go to a different view controller!
The header file
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#define METERS_PER_MILE 1609.344
#interface MSKSecondViewController :UIViewController<MKMapViewDelegate>
{
IBOutlet MKMapView *stillwellMapView;
int difficultyOfTrailOverlay;
}
#property (nonatomic, assign) CLLocationCoordinate2D mainEntranceToStillwellCoordinate;
#end
Here is the implementation file
#import "MSKSecondViewController.h"
#interface MSKSecondViewController ()
#end
#implementation MSKSecondViewController
#synthesize mainEntranceToStillwellCoordinate;
- (void)viewDidLoad
{
[super viewDidLoad];
stillwellMapView.delegate=self;
// Do any additional setup after loading the view, typically from a nib.
[self mainEntrancetoStillwellCoordinate];
[self bambooForestCoordinate];
}
- (void)mainEntrancetoStillwellCoordinate
{
MKPointAnnotation * main = [[MKPointAnnotation alloc]init];
CLLocationCoordinate2D mainLocation;
mainLocation.latitude = 40.831685;
mainLocation.longitude = -73.477453;
[main setCoordinate:mainLocation];
[main setTitle:#"Entrance"];
[main setSubtitle:#"Main"];
[stillwellMapView addAnnotation:main];
}
- (void)bambooForestCoordinate
{
MKPointAnnotation * bambooForest = [[MKPointAnnotation alloc]init];
CLLocationCoordinate2D bambooForestLocation;
bambooForestLocation.latitude = 40.829118;
bambooForestLocation.longitude = -73.466443;
[bambooForest setCoordinate:bambooForestLocation];
[bambooForest setTitle:#"Bamboo Forest"];
[bambooForest setSubtitle:#"Exit to Woodbury"];
[stillwellMapView addAnnotation:bambooForest];
}
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation
(id<MKAnnotation>)annotation
{
MKPinAnnotationView * annView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:nil];
UIButton *moreInformationButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[moreInformationButton addTarget:self action:#selector(moreInformationButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
annView.rightCalloutAccessoryView = moreInformationButton;
moreInformationButton.frame = CGRectMake(0, 0, 23, 23);
moreInformationButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
moreInformationButton.contentHorizontalAlignment =
UIControlContentHorizontalAlignmentCenter;
annView.pinColor =MKPinAnnotationColorGreen;
annView.animatesDrop = true;
annView.canShowCallout = TRUE;
return annView;
}
I'm not sure if this is what I need to add, and what needs to go inside here
-(void) moreInformationButtonPressed:(UIButton *)sender
{
}
Write below kind of code:
-(void) moreInformationButtonPressed:(UIButton *)sender
{
OtherViewController *controller = [[OtherViewController alloc]initWithNibName:#"OtherViewController" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
first you should make a tag that you can know which annotation is clicked
moreInformationButton.tag = someIndex;
then do the action you want
-(void) moreInformationButtonPressed:(UIButton *)sender
{
int index = sender.tag;
YourController *yc =[[[YourController alloc] initWithIndex:index] autorelease];
[self.navigationController pushViewController:scanView animated:YES];
}

dismissing modalview is not working

i m presenting modalviewcontroller without using delegate protocol. But want to dismiss modalviewcontroller using delegate protocol.
Basically i m pushing modalviewcontroller like this
- (void)displayModalViewaction: (id) sender
{
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[Infoviewcontroller alloc] init];
[self.view setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
UINavigationController *navigationController=[[UINavigationController alloc] init];
navigationController.navigationBar.tintColor = [UIColor brownColor];
[navigationController pushViewController:_viewController animated:YES];
[self.view addSubview:navigationController.view];
[_viewController release];
[navigationController release];
}
For dismissing modalview doing this
In the ModalViewController.h delegated protocol and method
#protocol ModalViewDelegate <NSObject>
-(void) dismissModalView:(UIViewController *) viewController;
#end
#interface Infoviewcontroller : UIViewController <ModalViewDelegate>
{
id<ModalViewDelegate> dismissDelegate;
}
#property (nonatomic, retain) id<ModalViewDelegate> dismissDelegate;
#end
In modalviewcontroller. m file
#synthesize dismissDelegate;
-(void) dismissModalView:(UIViewController *) viewController;
{
[self dismissModalViewControllerAnimated:YES];
}
#end
-(void) dismissView: (id)sender
{
[delegate dismissModalView:self];
}
-(void) dismissModalView:(UIViewController *) viewController;
{
[self.dismissModalViewController Animated:YES];
}
#end
But somehow it is not working when clicking on done button
UIButton* backButton = [UIButton buttonWithType:101];
[backButton addTarget:self action:#selector(dismissView:) forControlEvents:UIControlEventTouchUpInside];
[backButton setTitle:#"Done" forState:UIControlStateNormal];
// create button item
UIBarButtonItem* backItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
// add the button to navigation bar
self.navigationItem.leftBarButtonItem = backItem;
[backItem release];
Anyone have any clue that what i m missing in my code or what i m doing wrong. Help will be really appreciated.
Thanks
I would have liked to comment, but not enough privilege. Anyways AFAIK...
One does not 'push' a modal VC... it needs to be 'presented' like this..
[navigationController presentModalViewController:_viewController animated:YES];
Only a presented Modal VC will get dismissed on calling [self dismissModalViewControllerAnimated:YES];
OR, in case you really need to 'push' it.. then you need to 'pop' it to get back!
Hope it helps
Correct me if I'm wrong but wouldn't you want to define _viewController in your .h file and dismiss it with: [delegate dismissModalView:_viewController]; rather then dismissing self because self is not a view controller.
You are pushing onto the navigation's stack so no Modal was ever displayed you need to pop the view off the stack:
[self.navigationController popViewControllerAnimated:YES];
instead of:
[self dismissModalViewControllerAnimated:YES];

pushViewController issue

I've got a TabBar application and 2 views.
One view is a MKMapView with annotations and callouts etc. All works well. Clicking on the 'UIButtonTypeDetailDisclosure' button in the callout my 'showDetails' function fires (NSLOG..).
Now I want to push a DetailView in 'showDetails'. I'd have to either use pushViewController or presentModalViewController
#pragma mark - MKMap methods
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{
if([annotation isKindOfClass:[CustomPlacemark class]])
{
MKPinAnnotationView *newAnnotation = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:[annotation title]];
newAnnotation.pinColor = MKPinAnnotationColorGreen;
newAnnotation.animatesDrop = YES;
newAnnotation.canShowCallout = YES;
newAnnotation.enabled = YES;
//newAnnotation.pinColor=MKPinAnnotationColorPurple;
NSLog(#"Created annotation at: %f %f", ((CustomPlacemark*)annotation).coordinate.latitude, ((CustomPlacemark*)annotation).coordinate.longitude);
[newAnnotation addObserver:self
forKeyPath:#"selected"
options:NSKeyValueObservingOptionNew
context:#"GMAP_ANNOTATION_SELECTED"];
UIImageView *leftIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"leftIconView.png"]];
newAnnotation.leftCalloutAccessoryView = leftIconView;
[leftIconView release];
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
newAnnotation.rightCalloutAccessoryView = rightButton;
[newAnnotation autorelease];
return newAnnotation;
}
return nil;
}
- (void) showDetails:(id)sender {
NSLog(#"Annotation Click");
[self.navigationController pushViewController:self.detailViewController animated:YES];
// I want to push a new View here...
}
Unfortunately this doesn't do anything (No error / no action). I reckon it's because I don't have a navigationController to use pushViewController.
- (void) showDetails:(id)sender {
NSLog(#"Annotation Click");
[self.navigationController pushViewController:self.detailViewController animated:YES];
// I want to push a new View here...
}
i am trying to create and push a DetailViewController in the navigationController when my 'UIButtonTypeDetailDisclosure' button in notification is clicked. but navigationController is nil
Any idea what to add to my 'showDetails' function?
Much appreciated
You need to have a navigation controller before pushing views on it:
DetailViewController *detailController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:[NSBundle mainBundle]];
// this line calls the viewDidLoad method of detailController
detailController.view.hidden = NO;
UINavigationController *navigationController = [[UINavigationController alloc] detailController];
navigationController.navigationBarHidden = YES;
[navigationController setView:detailController.view];
[self.view addSubview:navigationController.view];
[detailController release];
[navigationController release];
Be careful this will initialize navigationController again and again if you do this in your showDetails:. So you need to initialize your navigation controller in eg. viewDidLoad and then you will be able to push your detailController onto it
If you want to push a view controller with a navigation controller, then your initial view must be within the navigation controller to begin with.
In your case, your tab bar controller should probably be put in the navigation controller if it isn't already. Then you can call your showDetails method the way you have done above. If it is in the nav controller, maybe you can post the code where you do that and I can try and offer more assistance.
Here is how you might do something like this in your applicationDidFinishLaunchingWithOptions: method
FirstViewController *fvc = [[FirstViewController alloc] init];
SecondViewController *svc = [[SecondViewController alloc] init];
UITabBarController *tabcon = [[UITabBarController alloc] init];
tabcon.viewControllers = [NSArray arrayWithObjects:fvc,svc,nil];
UINavigationController *navcon = [[UINavigationController alloc] initWithRootViewController:tabcon];
[self.window addSubview:navcon.view];
Then when you want to push a detail view controller, you just call:
DetailViewController *dvc = [[DetailViewController alloc] init];
[self.navigationController pushViewController:dvc];
If you set your view controllers as properties, you can call self.viewControllerName, just make sure you are allocating memory for them as well. Embedding your tab bar controller in a navigation controller like this gives you all the window dressing (back buttons, title bar, etc.) for free and it will adapt to your different views as they come on screen.

UITabBarController rotation problem with popViewControllerAnimated and selectedIndex (iPhone SDK)

This is a very important auto rotate issue and easy to reproduce.
My application has a UITabBarController. Each tab is a UINavigationController. Auto rotation is handled with normal calls to shouldAutorotateToInterfaceOrientation and didRotateFromInterfaceOrientation.
The interface rotates normally until I call UIViewController.popViewControllerAnimated and change UITabBarController.selectedIndex.
Steps to reproduce:
Create a demo Tab Bar Application.
Add the following code to the App Delegate .h file:#import <UIKit/UIKit.h>
#interface TestRotationAppDelegate : NSObject {
UIWindow *window;
UITabBarController *tabBarController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#end
// Redefine the interface to cach rotation messages
#interface UITabBarController (TestRotation1AppDelegate)
#end
Add the following code to the App Delegate .m file:#import "TestRotationAppDelegate.h"
#implementation TestRotationAppDelegate
#synthesize window;
#synthesize tabBarController;
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
return YES;
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
-(void)dealloc {
[tabBarController release];
[window release];
[super dealloc];
}
#end
#implementation UITabBarController (TestRotation1AppDelegate)
-(void)viewDidLoad {
[super viewDidLoad];
// Add a third tab and push a view
UIViewController *view1 = [[[UIViewController alloc] init] autorelease];
view1.title = #"Third";
UINavigationController *nav = [[[UINavigationController alloc] initWithRootViewController:view1] autorelease];
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObjectsFromArray:self.viewControllers];
[array addObject:nav];
self.viewControllers = array;
// Push view2 inside the third tab
UIViewController *view2 = [[[UIViewController alloc] init] autorelease];
[nav pushViewController:view2 animated:YES];
// Create a button to pop view2
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(50, 50, 220, 38);
[button setTitle:#"Pop this view" forState:UIControlStateNormal];
[button addTarget:self action:#selector(doAction) forControlEvents:UIControlEventTouchUpInside];
[view2.view addSubview:button];
}
-(void) doAction {
// ROTATION PROBLEM BEGINS HERE
// Remove one line of code and the problem doesn't occur.
[self.selectedViewController popViewControllerAnimated:YES];
self.selectedIndex = 0;
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
#end
The interface auto rotates normally until you tap the button on tab #3.
Your help will be geatly appreciated!
iPhone SDK 3.2 solves this issue.
With previous SDK use [self.selectedViewController popViewControllerAnimated:NO].