开发者

[NSCFString viewWillAppear:]: unrecognized selector sent to instance on iPhone 3G but not on simulator or iPhone 4

I've been looking for a solution for nearly 4 hours but I've been unable to find anything...

I've got an application with two tabs. The first one contains a Navigation controller, and the second a MKMapView. Everything is properly linked onto IB. This works fine on the simulator and on an iPhone4, but if I try on an iPhone 3G (I tried on two different actually), I've got a memory error.

Here is the stack trace :

2011-05-04 11:38:44.652 GeoSocial[8191:307] -[NSCFString viewWillAppear:]: unrecognized selector sent to instance 0x3e7b7040
2011-05-04 11:38:44.901 GeoSocial[8191:307] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString viewWillAppear:]: unrecognized selector sent to instance 0x3e7b7040'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x3759dc7b __exceptionPreprocess + 114
    1   libobjc.A.dylib                     0x32d9bee8 objc_exception_throw + 40
    2   CoreFoundation                      0x3759f3e3 -[NSObject(NSObject) doesNotRecognizeSelector:] + 98
    3   CoreFoundation                      0x37544467 ___forwarding___ + 506
    4   CoreFoundation                      0x37544220 _CF_forwarding_prep_0 + 48
    5   UIKit                               0x3597b7bc -[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:] + 220
    6   UIKit                               0x3597b6d4 -[UITabBarController transitionFromViewController:toViewController:] + 40
    7   UIKit                               0x3597ad40 -[UITabBarController _setSelectedViewController:] + 256
    8   UIKit                               0x35a83c4c -[UITabBarController setSelectedViewController:] + 20
    9   UIKit                               0x35a84890 -[UITabBarController _tabBarItemClicked:] + 316
    10  CoreFoundation                      0x37542a43 -[NSObject(NSObject) performSelector:withObject:withObject:] + 26
    11  UIKit                               0x35902f20 -[UIApplication sendAction:to:from:forEvent:] + 136
    12  UIKit                               0x35902e88 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 40
    13  UIKit                               0x35b69ee0 -[UITabBar _sendAction:withEvent:] + 424
    14  CoreFoundation                      0x37542a43 -[NSObject(NSObject) performSelector:withObject:withObject:] + 26
    15  UIKit                               0x35902f20 -[UIApplication sendAction:to:from:forEvent:] + 136
    16  UIKit                               0x35902e88 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 40
    17  UIKit                               0x35902e50 -[UIControl sendAction:to:forEvent:] + 52
    18  UIKit                               0x35902aa0 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 536
    19  UIKit                               0x35947340 -[UIControl sendActionsForControlEvents:] + 24
    20  UIKit                               0x35b66568 -[UITabBar(Static) _buttonUp:] + 116
    21  CoreFoundation                      0x37542a43 -[NSObject(NSObject) performSelector:withObject:withObject:] + 26
    22  UIKit                               0x35902f20 -[UIApplication sendAction:to:from:forEvent:] + 136
    23  UIKit                               0x35902e88 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 40
    24  UIKit                               0x35902e50 -[UIControl sendAction:to:forEvent:] + 52
    25  UIKit                               0x35902aa0 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 536
    26  UIKit                               0x359035cc -[UIControl touchesEnded:withEvent:] + 460
    27  UIKit                               0x358f4eb0 -[UIWindow _sendTouchesForEvent:] + 588
    28  UIKit                               0x358f44e4 -[UIWindow sendEvent:] + 396
    29  UIKit                               0x358d7c9c -[UIApplication sendEvent:] + 452
    30  UIKit                               0x358d73b4 _UIApplicationHandleEvent + 6824
    31  GraphicsServices                    0x33e77c88 PurpleEventCallback + 1048
    32  CoreFoundation                      0x3752f5cb __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 28
    33  CoreFoundation                      0x3752f589 __CFRunLoopDoSource1 + 164
    34  CoreFoundation                      0x37521835 __CFRunLoopRun + 580
    35  CoreFoundation                      0x3752150b CFRunLoopRunSpecific + 226
    36  CoreFoundation                      0x37521419 CFRunLoopRunInMode + 60
    37  GraphicsServices                    0x33e76d24 GSEventRunModal + 196
    38  UIKit                               0x3591d57c -[UIApplication _run] + 588
    39  UIKit                               0x3591a558 UIApplicationMain + 972
    40  GeoSocial                           0x00002ec1 main + 72
    41  GeoSocial                           0x00002e74 start + 40
)
terminate called after throwing an instance of 'NSException'

Somthing else is kinda weird : everytime I launch the application, and whatever is the device, I still have the same address for the instance (0x3e7b7040). I tried debugging step by step. The viewDidLoad method runs fine, but right after it (after a few steps into the assembly mode of xCode) the exception is thrown.

Does anyone have an idea or a lead to debug it?

Here is the concerned view controller code :

LastLocViewController.h

//
//  SecondViewController.h
//  LocateMe
//
//  Created by Hugo Briand on 07/04/11.
//  Copyright 2011 Neotiq. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>

#import "LocateMeAppDelegate.h"

@interface LastLocViewController : UIViewController <CLLocationManagerDelegate, AdBannerDelegate> {
    IBOutlet MKMapView *mapView;
    IBOutlet ADBannerView *adBanView;
}

@property (nonatomic, retain) IBOutlet MKMapView *mapView;
@property (nonatomic, retain) IBOutlet UIView *contentView;
@end

LastLocViewController.m

//
//  SecondViewController.m
//  LocateMe
//
//  Created by Hugo Briand on 07/04/11.
//  Copyright 2011 Neotiq. All rights reserved.
//

#import "LastLocViewController.h"
#import "CLContact.h"
#import "CLContactManager.h"

@interface LastLocViewController()

-(void)recenterRegion;
@end


@implementation LastLocViewController

@synthesize mapView;
@synthesize contentView;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    [super viewDidLoad];
    if (![CLLocationManager locationServicesEnabled]) {
        UIAlertView *error = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil) message:NSLocalizedString(@"You need to enable location services for this application in your Settings", nil) delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [error show];
        [error release];
    }
    NSMutableArray *locations = [[NSMutableArray alloc] init];
    LocateMeAppDelegate *del = (LocateMeAppDelegate *) [[UIApplication sharedApplication] delegate];
    for (NSArray *ac in [[del.contactManager clContacts] allValues]) {
        for (CLContact *c in ac) {
            if (c.coordinate.latitude !=0 || c.coordinate.longitude != 0) {
                [locations addObject:c];
            }
        }
    }
    [mapView addAnnotations:[NSArray arrayWithArray:locations]];
    [locations release];
    [self recenterRegion];
#ifdef ADD_ENABLED
        // Configuring ads
    if (adBanView != del.adBanner) {
        adBanView = del.adBanner;
        del.adBanDelegate = self;
    }
    [self layoutForCurrentOrientation:NO];
#else
    [adBanView removeFromSuperview];
#endif

}

-(void)layoutForCurrentOrientation:(BOOL)animated
{
#ifdef ADD_ENABLED
    LocateMeAppDelegate *del = (LocateMeAppDelegate *)[[UIApplication sharedApplication] delegate];
    ADBannerView *sharedAdBan = del.adBanner;
    CGFloat animationDuration = animated ? 0.2f : 0.0f;
        // by default content consumes the entire view area
    CGRect contentFrame = self.view.bounds;
        // the banner still needs to be adjusted further, but this is a reasonable starting point
        // the y value will need to be adjusted by the banner height to get the final position
    CGPoint bannerOrigin = CGPointMake(CGRectGetMinX(contentFrame), CGRectGetMaxY(contentFrame));
    CGFloat bannerHeight = 0.0f;

        // First, setup the banner's content size and adjustment based on the current orientation
        sharedAdBan.currentContentSizeIdentifier = (&ADBannerContentSizeIdentifierPortrait != nil) ? ADBannerContentSizeIdentifierPortrait : ADBannerContentSizeIdentifier320x50; 
    bannerHeight = sharedAdBan.bounds.size.height;

        // Depending on if the banner has been loaded, we adjust the content frame and banner location
        // to accomodate the ad being on or off screen.
        // This layout is for an ad at the bottom of the view.
    if(sharedAdBan.bannerLoaded)
    {
        contentFrame.size.height -= bannerHeight;
        bannerOrigin.y -= bannerHeight;
    }
    else
    {
        bannerOrigin.y += bannerHeight;
    }

        // And finally animate the changes, running layout for the content view if required.
    [UIView animateWithDuration:animationDuration
                     animations:^{
                         mapView.frame = contentFrame;
                         [mapView layoutIfNeeded];
                         sharedAdBan.frame = CGRectMake(bannerOrigin.x, bannerOrigin.y, sharedAdBan.frame.size.width, sharedAdBan.frame.size.height);
                     }];
#endif
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}


- (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.
}


- (void)viewDidUnload
{
    [super viewDidUnload];
#ifdef ADD_ENABLED
    LocateMeAppDelegate *del = (LocateMeAppDelegate *)[[UIApplication sharedApplication] delegate];
    [del.adBanner removeFromSuperview];
    del.adBanDelegate = nil;
#endif

}

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
#ifdef ADD_ENABLED
    LocateMeAppDelegate *del = (LocateMeAppDelegate *)[[UIApplication sharedApplication] delegate];
    if (adBanView != del.adBanner) {
        adBanView = del.adBanner;
        del.adBanDelegate = self;
    }
    [self layoutForCurrentOrientation:NO];
#endif
}


-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    NSLog(@"CLContactLocSyncVC viewWillDisappear");
#ifdef ADD_ENABLED
    LocateMeAppDelegate *del = (LocateMeAppDelegate *)[[UIApplication sharedApplication] delegate];
    [del.adBanner removeFromSuperview];
    del.adBanDelegate = nil;
    [del.currentSyncLoc setDelegate:nil];
#endif
}


-(void)recenterRegion {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    CLLocationDegrees maxLat=-90;
    CLLocationDegrees minLat=90;
    CLLocationDegrees maxLon=-180;
    CLLocationDegrees minLon=180;


    for(id ann in [mapView annotations]) {
        if ([ann isKindOfClass:[CLContact class]]) {
            minLat = MIN(minLat, [ann coordinate].latitude);
            minLon = MIN(minLon, [ann coordinate].longitude);
          开发者_高级运维  maxLat = MAX(maxLat, [ann coordinate].latitude);
            maxLon = MAX(maxLon, [ann coordinate].longitude);
        }
    }



    CLLocationDegrees spLat = MIN(MAX(ABS([mapView userLocation].coordinate.latitude-minLat),
                                      ABS([mapView userLocation].coordinate.latitude-maxLat))*2*1.1, 90);
    CLLocationDegrees spLon = MIN(MAX(ABS([mapView userLocation].coordinate.longitude-minLon),
                                      ABS([mapView userLocation].coordinate.longitude-maxLon))*2*1.1, 180);

    MKCoordinateSpan sp = MKCoordinateSpanMake(spLat, spLon);
    MKCoordinateRegion reg = MKCoordinateRegionMake([mapView userLocation].coordinate, sp);
    @try {
        [mapView setRegion:reg animated:YES];
    }
    @catch (NSException *e) {
        NSLog(@"caught invalid argument exception on setRegion, continuing : %@", [e description]);
    }

    [self performSelector:@selector(recenterRegion) withObject:nil afterDelay:10.0];

    [pool release];
}

- (void)dealloc
{
#ifdef ADD_ENABLED
    LocateMeAppDelegate *del = (LocateMeAppDelegate *)[[UIApplication sharedApplication] delegate];
    [del.adBanner removeFromSuperview];
    del.adBanDelegate = nil;
#endif
    [super dealloc];
}



@end

Thanks in advance !

EDIT

I finally got it after listening to Andrew's second advice. The issue was in the viewDidLoad method. This block :

NSMutableArray *locations = [[NSMutableArray alloc] init];
    LocateMeAppDelegate *del = (LocateMeAppDelegate *) [[UIApplication sharedApplication] delegate];
    for (NSArray *ac in [[del.contactManager clContacts] allValues]) {
        for (CLContact *c in ac) {
            if (c.coordinate.latitude !=0 || c.coordinate.longitude != 0) {
                [locations addObject:c];
            }
        }
    }
    [mapView addAnnotations:[NSArray arrayWithArray:locations]];
    [locations release];

was incorrect if I had no location in the locations array. Somehow it led to a crash. I added a check on the size of the array and that made it.

Thanks for your reply Andrew !


I'd recommend running your code in Instruments using the NSZombie target. Alternatively you may try running with the NSZombieEnabled environment variable set in your application executable options.

Doing this should help you get to the root of the problem.

Other than that, try stepping away for a few hours and come back to it with a fresh head and re-question all your existing assumptions.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜