Question

Just to preface, I am new to iOS development. I have looked around for awhile to try and find an answer, whether on here or through Google.

My application loads into a mapview with annotations. If a user taps on one of the annotations a callout view with an accessory button displays. The problem I am having is in the method that is called when the accessory button is tapped. I am wanting to display a detailview for the specific annotation, but when I tap the accessory button the app crashes with SIGABRT.

// method that provides the view for when the callout accessory button is tapped
-               (void)mapView:(MKMapView *)mapView 
               annotationView:(MKAnnotationView *)view 
calloutAccessoryControlTapped:(UIControl *)control
{
    // grabs the annotation's title from the annotation view
    NSString *viewTitle = view.annotation.title;

    // grabs corresponding POI object for map annotation
    PointOfInterest *object = [[PointOfInterest alloc] init];
    object = [dictionary objectForKey:(NSString *)viewTitle];

    // assigns title and subtitle ivars to variables to be passed into detailviewcontroller init
    NSString *title = object._title;
    NSString *subtitle = object._subtitle;
    UIImage *picture = object._picture;
    NSString *description = object._description;

    // releases POI object after all the information has been taken from it
    [object release];

    // inits detailVC
    DetailVC *detailVC = [[DetailVC alloc] initWithNibName:@"DetailVC" 
                                                    bundle:[NSBundle mainBundle]];

    // sets the nsstring ivars in the DVC which correspond to the POI information
    detailVC.thetitleText = title;
    detailVC.thesubtitleText = subtitle;
    detailVC.thepictureImage = picture;
    detailVC.thedescriptionText = description;

    // sets the "back" button on the navigation controller to say "Back to Map"
    UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle:@"Back to Map" 
                                                                      style:UIBarButtonItemStyleBordered 
                                                                     target:nil 
                                                                     action: nil];
    [[self navigationItem] setBackBarButtonItem: newBackButton];
    [newBackButton release];

    // pushes navcontroller onto the stack and releases the detail viewcontroller
    [self.navigationController pushViewController:detailVC animated:YES];
    [detailVC release];
}

I haven't added the picture and description yet, because I am just trying to get the view to show with the Title and Subtitle.

Here is the DetailViewController class code Header:

@interface DetailViewController : UIViewController {
    IBOutlet UIScrollView *scrollview;
    IBOutlet UILabel *thetitle;
    NSString *thetitleText;
    IBOutlet UILabel *thesubtitle;
    IBOutlet UIImage *thepicture;
    IBOutlet UITextView *thedescription;
}

@property (nonatomic, retain) UIScrollView *scrollview;
@property (nonatomic, retain) UILabel *thetitle;
@property (nonatomic, retain) NSString *thetitleText;
@property (nonatomic, retain) UILabel *thesubtitle;
@property (nonatomic, retain) UIImage *thepicture;
@property (nonatomic, retain) UITextView *thedescription;

// method that creates the custom detail view with the corresponding information from
// the point of interest objects
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil title:(NSString*)title subtitle:(NSString *)subtitle picture:(UIImage *)picture description:(NSString *)description;

@end

implementation:

@implementation DetailViewController

@synthesize scrollview, thetitle, thesubtitle, thepicture, thedescription, thetitleText;


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil title:(NSString *)title subtitle:(NSString *)subtitle picture:(UIImage *)picture description:(NSString *)description;
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        NSLog(@"view initialized");
}
return self;
}

- (void)dealloc
{
    [scrollview release];
    [thetitle release];
    [thesubtitle release];
    [thepicture release];
    [thedescription release];
    [thetitleText release];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"view did load");

    [thetitle setText:self.thetitleText];
    NSLog(@"thetitle text set");


// Do any additional setup after loading the view from its nib.
//    [thetitle setText:title];
//    NSLog(@"set title");
//    [thesubtitle setText:subtitle];
//    NSLog(@"set subtitle");
//    thepicture = picture;
//    [thedescription setText:description];
//    NSLog(@"set description");
}

Here is the SIGABRT output:

2011-07-12 19:05:06.678 mkeBOAT[1687:ef03] Callout Accessory Tapped

2011-07-12 19:05:06.679 mkeBOAT[1687:ef03] US Bank Tower

2011-07-12 19:05:06.680 mkeBOAT[1687:ef03] (null)

2011-07-12 19:05:06.680 mkeBOAT[1687:ef03] (null), (null)

2011-07-12 19:05:06.680 mkeBOAT[1687:ef03] view initialized

2011-07-12 19:05:06.711 mkeBOAT[1687:ef03] * Terminating app due to uncaught exception

'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key description.'

I am don't think the dictionary is working correctly because it is outputting null for the values that should actually have something.

Thanks for any and all help!

Was it helpful?

Solution

you shouldn't do this

[detailViewController autorelease];

before pushing detailViewController to stack.

you should push it into the navigation stack first then release it since you don't need it anymore and the navigation stack is now the owner of the detailView controller object.

so instead of doing this

[detailViewController autorelease];

// this is the line that breaks with SIGABRT
[self.navigationController pushViewController:detailViewController animated:YES];

do this

[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];

More info:

SIGABRT usually happens when there is remaining referencing outlets in your IB but the object in ur controller is not existing anymore.

You should check all your referencing outlets.

OTHER TIPS

Make sure the Class of Files Owner in your XIB is set to DetailViewController.

I think it is because you have your @property set to copy it should be retain

There is some errors in your implementation :

1) Don't call parent method with fixed value :

self = [super initWithNibName:@"DetailViewController" bundle:nil];

instead use parameters :

self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

2) Your thetitle and thesubtitle properties are IBOutlet UILabel but you use copy instead retain, change copy by retain

3) You initialize your UILabel (thetitle and thesubtitle) text in the init method but in this method, the properties are not already defined (thetitle and thesubtitle = nil).

You should instead use NSString properties and set the text of UILabel in the viewDidLoad method with your NSString properties.

And do the same for the UITextField thedescription property.

And don't forget to release all of your properties copied or retained in dealloc and reset your IBOutlet properties in your viewDidUnload method.

For the point 3 :

Add NSString properties to your DetailViewController (and don't forget to synthesize and release it in dealloc) :

@property (nonatomic, retain) NSString *thetitleText;

next, before pushViewController, add :

detailViewController.thetitleText = title;

and finally in your viewDidLoad method of your DetailViewController, add :

[thetitle setText:self.thetitleText];

And do the same for your other labels.

After restarting and creating a new Detail View Controller, I am pretty sure I had my view linked to the image instead of the actual view. To compound this, I also believe that my scrollview was really mucking things up. If anyone would like to see the code that actually works just let me know. Thank you to all those contributed!! What a great community SOverflow is!

Read carefully the code...

You did initialized object using :

PointOfInterest *object = [[PointOfInterest alloc] init];.

Why re-assigning object like so :

object = [dictionary objectForKey:viewTitle]; ?

So, no matter in this issue, but here is a leak. Also, I am pretty sure the crash is due to reassigning object to the value with the viewTitle corresponding key, trying to send a message to it later, and as you just think of manipulating an object of type PointOfInterest.

Hope this helps.

Make sure that your View Controller has a view. Mine was bombing (SIGABRT) just as described in the question because I had forgotten in IB to connect up the view outlet (which is usually created for you in your xib file) to my controller's view.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top