【发布时间】:2017-08-30 02:35:33
【问题描述】:
我有一个选项卡式应用程序。在情节提要中,其中一个选项卡是导航控制器。在根视图上,会弹出一个 UIImagePickerController 以便用户拍摄或选择照片。
/*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 的viewDidLoad 方法中,它将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];
}
认为这是一个释放问题,我试图注释掉所有涉及的释放方法,但问题仍然存在。我认为将 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];
}
它现在转到下一个视图,但应用程序随后崩溃并出现相同的异常代码。
我已经启用了 Zombies 并且还在断点导航器中添加了异常断点。我正在努力将我的代码版本放到 git 上,以便其他人可以体验我的问题并可能找到解决方案。
控制台中打印的错误:
2017-08-30 00:14:37.034 Leaflet-US[86918:4332982] *** -[SnapItViewController retain]: message sent to deallocated instance 0x7fae4470d4c0
【问题讨论】:
-
自动发布?你在使用 ARC 吗?
-
我继承了应用程序,所以有些代码是旧的。我尝试删除自动释放,但问题仍然存在
-
你能发布你所有的崩溃日志吗?
-
当然——如果发生崩溃,调试导航器 xcode 中的线程会跳转到整个崩溃日志吗?
-
SnapItViewController在哪里?崩溃是关于它的,但我看不到相关代码。对了,你在CollectionDetailViewController的viewDidLoad方法中漏掉了[super viewDidLoad]
标签: ios objective-c exception runtimeexception