2017-08-30 75 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