简体   繁体   中英

iOS - Unexpected crash when popping and pushing a view controller with a MKMapView

Hi there can anyone help me with the following problem: I have a ViewController with a MKMapView inside of it, and when i pop this view everything is alright but when i try to push this ViewController back in my NavigationController's stack my app crashes unexpectedly. I tried to fix this problem by enabling NSZombie and it worked fine while running from xcode, but when i tried to run it in the simulator (and on my iPhone) without using xcode and it still crashes. I also tried to make my mapview delegete nil in ViewWillDissapear, ViewDidDissapear and dealloc but i still have the same problem. Can anyone help me with this?

This is the log output when the app crashes:

-[__NSCFType observedViewControllerChange:]: unrecognized selector sent to instance 0x79a6f50 2012-09-14 11:28:13.878* **[456:12503] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType observedViewControllerChange:]: unrecognized selector sent to instance 0x79a6f50' * First throw call stack: (0x19af022 0x179ecd6 0x19b0cbd 0x1915ed0 0x1915cb2 0x12c3a29 0x197a855 0x197a778 0x120819a 0x9d9c97 0xb810be 0xb813c7 0xb81436 0x931e49 0x931f34 0x6c0b54 0x1f2c509 0x18e6803 0x18e5d84 0x18e5c9b 0x30967d8 0x309688a 0x901626 0x46ad 0x2d55) terminate called throwing an exception(lldb)

I am using arc. And here is some code: I do a lot of things in my viewDidLoad function and i think that the problem might be here this is the code:

This the .h:

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/Corelocation.h>
#import "AddressViewController.h"
#import "Utilities.h"
#import "MarqueeLabel.h"
#import "CustomButton.h"



@interface LocationViewController : UIViewController<MKMapViewDelegate,CLLocationManagerDelegate,UIGestureRecognizerDelegate>{
    CLLocationManager *locationManager;
    MKPointAnnotation *centerAnnotation;
    int initialState;
    NSDictionary * json;
    bool google;
    bool isBackgroundRunning;
    double x;
    CLLocationCoordinate2D selectedCoordinate;
    MarqueeLabel *continuousLabel;
    __weak IBOutlet CustomButton *cont;
    UILongPressGestureRecognizer *lgr;
    UIPanGestureRecognizer *panGesture;
    UIPinchGestureRecognizer *pinchGesture;
    UISwipeGestureRecognizer *swipeGesture;
    __weak IBOutlet UIButton *myLoc;
    BOOL first;

}
@property (strong, nonatomic) IBOutlet MKMapView *myMapView;
- (IBAction)showMe:(id)sender;
@property (strong, nonatomic) MKPointAnnotation *centerAnnotation;

@end




- (void)viewDidLoad
{
    [super viewDidLoad];
    first = YES;
    initialState = YES;
    nrGooglePosts = 0;

    [self.myMapView setShowsUserLocation:YES ];


    myMapView.centerCoordinate = myMapView.userLocation.coordinate;
    locationManager = [[CLLocationManager alloc] init];
    [locationManager setDelegate:self];
    [locationManager setDistanceFilter:kCLDistanceFilterNone];
    [locationManager setDesiredAccuracy:kCLLocationAccuracyBest];


    NSMutableArray *userL =[[NSUserDefaults standardUserDefaults] objectForKey:@"user"];
    if([userL count] == 0) NSLog(@"user nu e salvat");
    [[Utilities get] setName:[[userL valueForKey:@"name"] objectAtIndex:0]];
    [[Utilities get] setPhone:[[userL valueForKey:@"phone"] objectAtIndex:0]];
    [[Utilities get] setCode:[[userL valueForKey:@"code"] objectAtIndex:0]];
    [[Utilities get] setUserId:[[userL valueForKey:@"userid"] objectAtIndex:0]];


    centerAnnotation = [[MKPointAnnotation alloc] init];
    MKPointAnnotation * pc = [[MKPointAnnotation alloc] init];
    pc.coordinate = myMapView.centerCoordinate;
    pc.title = @"Map Center";
    pc.subtitle= [[NSString alloc] initWithFormat:@"%f, %f",pc.coordinate.latitude,pc.coordinate.longitude];    
    [self.myMapView addAnnotation:pc];
    centerAnnotation = pc;

    lgr= [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
    lgr.minimumPressDuration=0.1;
    lgr.allowableMovement = 5;
    lgr.delegate = self ;
    [myMapView addGestureRecognizer:lgr];

    panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
    panGesture.delegate = self;
    [myMapView addGestureRecognizer:panGesture];

    pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
    pinchGesture.delegate = self;
    [myMapView addGestureRecognizer:pinchGesture];

    swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
    swipeGesture.delegate = self;
    [myMapView addGestureRecognizer:swipeGesture];


    NSMutableArray * arr=[[NSUserDefaults standardUserDefaults ] objectForKey:@"locationList"];
    if([arr count]){
        for(int i = 0 ; i < [arr count] ; i++ ){
            NSMutableDictionary * adr = [[arr objectAtIndex:i] mutableCopy];
            if(adr){
                CLLocationDegrees lat = [[adr objectForKey:@"latitude"] doubleValue] ;
                CLLocationDegrees lon = [[adr objectForKey:@"longitude"] doubleValue] ;
                CustomMKAnnotation *ann = [[CustomMKAnnotation alloc] init ];
                CLLocationCoordinate2D coord = { lat, lon };

                ann.coordinate = coord;

                ann.title = [adr objectForKey:@"street"] ;   

                ann.subtitle = [[NSString alloc] initWithFormat:@"Nr:%@  Bl:%@  Sc:%@",[adr objectForKey:@"number"],[adr objectForKey:@"bloc"],[adr objectForKey:@"scara"]];

               MKAnnotationView *aux = [[MKAnnotationView alloc] initWithAnnotation:ann reuseIdentifier:nil];  
                UIImage *poza = [UIImage imageNamed:@"star.png"];
                UIImageView *pic = [[UIImageView alloc] initWithImage:poza];
                [aux addSubview:pic];
                aux.canShowCallout = YES;
                [myMapView addAnnotation:aux.annotation];


            }

        }
    }
    google = YES;
    json = [self getLocationFromGoogleWithCoordinates:myMapView.userLocation.coordinate];
    NSString *status = [[NSString alloc] initWithFormat:@"%@",[json objectForKey:@"status"]];
    if([status compare:@"ZERO_RESULTS"] == 0 && [status compare:@"OVER_QUERY_LIMIT"] == 0)
    {
        google=NO;
        NSLog(@"%@",status);
    }

    continuousLabel = [[MarqueeLabel alloc] initWithFrame:CGRectMake(32, 20, 191, 20) rate:50.0f andFadeLength:10.0f];
    continuousLabel.marqueeType = MLContinuous;
    continuousLabel.numberOfLines = 1;
    continuousLabel.opaque = NO;
    continuousLabel.enabled = YES;
    continuousLabel.shadowOffset = CGSizeMake(0.0, -1.0);
    continuousLabel.textAlignment = UITextAlignmentLeft;

    continuousLabel.backgroundColor = [UIColor clearColor];
    continuousLabel.font = [UIFont boldSystemFontOfSize:13];
    continuousLabel.text = [[Utilities get] streetName];
    [continuousLabel setBackgroundColor:[UIColor clearColor]];
    [continuousLabel setTextColor:[UIColor whiteColor]];
    continuousLabel.opaque = NO ;
    myLoc.opaque=NO;
    [myLoc setBackgroundColor:[UIColor clearColor]];
    [self.view addSubview:continuousLabel];


    [logoutButton setTitle:@"Log Out" forState:UIControlStateNormal];
    [logoutButton addTarget:self action:@selector(logout:) forControlEvents:UIControlEventTouchUpInside];


    UIBarButtonItem *logoutBarButton = [[UIBarButtonItem alloc] initWithCustomView:logoutButton]; 
    self.navigationItem.leftBarButtonItem = logoutBarButton;


    [self.navigationController.navigationBar setBackgroundColor:[UIColor clearColor]];



}
- (void) viewWillDisappear:(BOOL)animated
{

    [self.navigationController setNavigationBarHidden:YES animated:animated];

    [self stopTrackingLocation];

    [myMapView removeAnnotations:myMapView.annotations];
      self.myMapView.delegate = nil;

      self.view = nil;
    [super viewWillDisappear:animated];
}


- (void)stopTrackingLocation
{
    if (myMapView.showsUserLocation)
    {
        // Crashes here
        myMapView.showsUserLocation = NO;
    }
}

As I see you are using ARC.

Hey man, do not do this:

self.view = NULL. //REMOVE THIS!!!!

You cannot push UIViewController again, because there is no UIVIew related to it. It will make a crash in UINavigationController, because there is nothing actually to push.

The second problem, which doesn't make crash but have a place. You are removing Map View delegate. But if you are going to push this controller again, the second time map view will be disabled.

You should move this functionality to the dealloc method. And you should show user location in viewWillAppear: method, not in viewDidLoad: because this method will be executed only once. It will not take effect, when you will try to push your UIVIewController second time. So please change this functionality:

- (void) viewWillAppear:(BOOL)animated{
     [self.myMapView setShowsUserLocation:YES ];
}

- (void) viewWillDisappear:(BOOL)animated
{

    [self.navigationController setNavigationBarHidden:YES animated:animated];

    [self stopTrackingLocation];

    [myMapView removeAnnotations:myMapView.annotations];

    [super viewWillDisappear:animated];
}

-(void) dealloc{
     self.myMapView.delegate = nil;
     //In ARC we don't call [super dealloc]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM