2017-08-30 73 views
0

我有一个选项卡式应用程序。在故事板中,其中一个选项卡是导航控制器。在根视图上,UIImagePickerController弹出,以便用户可以拍摄或选择一张照片。Push ViewController生成运行时异常

/*SnapItViewController.m*/ 
#import "SnapItViewController.h" 
#import "FirstViewController.h" 
#import "CollectionListViewController.h" 
#import <sys/utsname.h> 

@interface SnapItViewController() 

@end 

@implementation SnapItViewController 
@synthesize fetchedResultsController; 
@synthesize currentLocation; 

#pragma mark View lifecycle 

- (void)awakeFromNib 
{ 
    // Listen to takePicture notifications 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(TakePicture) name:@"takePicture" object:nil]; 
    [super awakeFromNib]; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    ipc = [[UIImagePickerController alloc] init]; 
    ipc.delegate = self; 
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) 
    { 
     ipc.sourceType = UIImagePickerControllerSourceTypeCamera; 
     [self presentViewController:ipc animated:YES completion:NULL]; 
    }else{ 
     ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 
     //launch image picker view controller 
     [self presentViewController:ipc animated:YES completion:nil]; 
    } 
    // Do any additional setup after loading the view. 

} 

- (void)viewWillAppear:(BOOL)animated { 

    self.navigationController.navigationBarHidden = YES; 

    [super viewWillAppear:animated]; 
} 

- (void)viewDidAppear:(BOOL)animated 
{  
    [super viewDidAppear:animated]; 
} 
- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
} 
#pragma mark - ImagePickerController Delegate 
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { 

    UIImage* theImage = [info objectForKey:UIImagePickerControllerOriginalImage]; 

    if(picker.sourceType == UIImagePickerControllerSourceTypeCamera) 
    { 
     UIImageWriteToSavedPhotosAlbum(theImage, nil, nil, nil); 
    } 
    int height = -1; 
    if([[NSUserDefaults standardUserDefaults] integerForKey:@"reduce_image"] == 0){ 
     height = 640; 
    } else if ([[NSUserDefaults standardUserDefaults] integerForKey:@"reduce_image"] == 1) { 
     height = 1024; 
    } else { 
     height = 1600; 
    } 

    UIImage* resizedImageForUpload = [UtilityFunctions scaleAndRotateImage:theImage maxResolution:height]; 
    NSData* imageDataForUpload = UIImageJPEGRepresentation(resizedImageForUpload, 1); // reduced image! 

    NSString *userDataset = [UtilityFunctions retrieveFromUserDefaults:@"dataset"]; 

    [self didPickImage:imageDataForUpload atLocation:currentLocation 
        userDataset: userDataset]; 
    [picker dismissViewControllerAnimated:YES completion:nil];  
    [mLocationManager stopUpdatingLocation];  
    [self release]; 
    [self dismissViewControllerAnimated:YES completion:NULL]; 
} 

-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{ 
     [picker dismissViewControllerAnimated:YES completion:nil];  
} 

- (void)pushChildControllerForCollectedLeaf:(CollectedLeaf*)theCollectedLeaf imageToUpload:(NSData*)imageToUpload animated:(BOOL)animated 
{ 
    CollectionDetailViewController* childController = [[[CollectionDetailViewController alloc]initWithNibName:@"CollectionDetailViewController" bundle:nil] autorelease]; 
    childController.collectedLeaf = theCollectedLeaf; 

    //// Pass the image from image picker to Collection Detail View, and it'll handles the upload. //// 
    //// Set to nil for existing collections. //// 
    if (imageToUpload) 
    { 
     childController.imageToUpload = imageToUpload; 
    } 

    childController.hidesBottomBarWhenPushed = YES; 
    self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStylePlain target:nil action:nil]; 

    [self.navigationController pushViewController:childController animated:animated]; 
} 

- (void)pushChildControllerForCollectedLeaf:(CollectedLeaf*)theCollectedLeaf imageToUpload:(NSData*)imageToUpload 
{ 
    [self pushChildControllerForCollectedLeaf:theCollectedLeaf imageToUpload:imageToUpload animated:YES]; 
} 

#pragma mark Leaflet Photo Picker Delegate 

- (void)didPickImage:(NSData*)imageData atLocation:(CLLocation*)cLocation userDataset:(NSString *)userDataset 
{ 
    //// Creates a new Collected Leaf //// 
    CollectedLeaf* collectedLeaf = (CollectedLeaf*)[NSEntityDescription insertNewObjectForEntityForName:@"CollectedLeaf" inManagedObjectContext:[self.fetchedResultsController managedObjectContext]]; 

    //// Stores the geo-location to mCollectedLeaf //// 
    if (cLocation) 
    { 
     collectedLeaf.latitude = [NSString stringWithFormat:@"%f", cLocation.coordinate.latitude]; 
     collectedLeaf.longitude = [NSString stringWithFormat:@"%f", cLocation.coordinate.longitude]; 
     collectedLeaf.altitude = [NSString stringWithFormat:@"%f", cLocation.altitude]; 

    } 
    else 
    { 
     collectedLeaf.latitude = kGeoLocationNotAvailable; 
     collectedLeaf.longitude = kGeoLocationNotAvailable; 
     collectedLeaf.altitude = kGeoLocationNotAvailable; 
    } 

    collectedLeaf.collectedDate = [NSDate date]; 
    collectedLeaf.selectedSpecies = kUnknownSpecies; 
    collectedLeaf.userDataset = userDataset; 

    [self pushChildControllerForCollectedLeaf:collectedLeaf imageToUpload:imageData animated:YES]; 
} 

@end 

用户选择照片后,会将CollectionDetailViewController推送到导航堆栈上。在方法CollectionDetailViewController中,它将CollectionDetailDataViewController推送到导航堆栈上,导航堆栈显示UITable。

/*CollectionDetailViewController.m */ 
- (void)viewDidLoad 
{ 
    containerView.frame = [self largeFrame]; 

    dataVC = [[CollectionDetailDataViewController alloc] init]; 
    dataVC.delegate = self; 
    dataVC.collectedLeaf = self.collectedLeaf; 
    dataVC.view.frame = [self normalFrame]; 

    [self.navigationController pushViewController:dataVC animated:NO]; 
    [super viewDidLoad]; 
} 

当我点击UITable的细胞,它推动一个SpeciesViewController应用程序崩溃与Thread 1: exc_breakpoint (code=exc_i386_bpt subcode=0x0)

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    RankedSpecies *theRankedSpecies = [fetchedResultsController objectAtIndexPath:indexPath]; 
    SpeciesViewController* speciesController = [[[SpeciesViewController alloc]initWithNibName:@"SpeciesViewController" bundle:nil] autorelease]; 
    speciesController.theSpecies = theRankedSpecies.Species; 
    [[tableView cellForRowAtIndexPath:indexPath] setSelected:NO animated:YES]; 
    [self.navigationController pushViewController:speciesController animated:YES]; 

} 

认为这是一个释放问题,我试图注释掉所有涉及的dealloc方法,但问题依然存在。我认为替换pushviewcontroller添加SpeciesViewController作为子视图CollectionDetailDataViewController

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    RankedSpecies *theRankedSpecies = [fetchedResultsController objectAtIndexPath:indexPath]; 
    SpeciesViewController* speciesController = [[[SpeciesViewController alloc]initWithNibName:@"SpeciesViewController" bundle:nil] autorelease]; 
    speciesController.theSpecies = theRankedSpecies.Species; 
    [[tableView cellForRowAtIndexPath:indexPath] setSelected:NO animated:YES]; 

    [self addChildViewController:speciesController]; 
    [self.view addSubview:speciesController.view]; 
    [speciesController didMoveToParentViewController:self]; 

} 

现在进入下一个视图,但随后的应用程序具有相同异常代码崩溃。

我已启用僵尸,并在断点导航器中添加了异常断点。我正在努力将我的代码版本加入到git中,以便其他人可以体验我的问题并可能确定解决方案。

错误印在康寿:

2017-08-30 00:14:37.034 Leaflet-US[86918:4332982] *** -[SnapItViewController retain]: message sent to deallocated instance 0x7fae4470d4c0 

崩溃堆栈跟踪: enter image description here

+1

autorelease?你正在使用ARC? –

+0

我继承了应用程序,所以一些代码是旧的。我试图删除autorelease,但问题仍然存在 – Matt

+0

你可以发布所有的崩溃日志? –

回答

0
[picker dismissViewControllerAnimated:YES completion:nil]; 
[mLocationManager stopUpdatingLocation]; 
[self release]; 
[self dismissViewControllerAnimated:YES completion:NULL]; 

您在同一时间辞退2个viewControllers animately?也许你可以尝试解散完成块中的第二次解雇。 self dismissViewControllerAnimated不明确,因为它可以关闭视图控制器或关闭自己。我认为你想解雇自己,那就是SnapItViewController,所以你先发布SnapItViewController,然后发一个解雇消息给它,这显然是错误的。

您发布了SnapItViewController的代码,但仍然没有发布您称之为的地方。

+0

SnapItViewController是“捕捉它”选项卡上的rootview控制器 - 我没有编写代码来调用它,StoryBoard为我设置它 – Matt

+0

我关闭了UIImagePickerViewController,然后关闭SnapItViewController,然后在didPickImage,我推出了一个新的观点,这个观点肯定不是很好。但是,如果我删除第二个解雇,我的程序崩溃。 – Matt

0

将溶液最终被从didFinishPickingMediaWithInfo在SnapItViewController除去

[self release] 

[self dismissViewControllerAnimated:YES completion:NULL]; 

+0

但是,我不知道这是为什么.... ....任何想法? – Matt

+0

我无法回想起自己看到的释放......对我来说,这似乎是一个非常糟糕的主意。有没有一个有效的用例呢? – ghostatron

+0

另外,假设你使用ARC,你应该很少需要调用release。 – ghostatron