开发者

iphoneSDK: UINavigationController Back button is causing app to crash

开发者 https://www.devze.com 2022-12-10 22:53 出处:网络
My app is crashing when I move between ViewControllers. This is the sequence that causes the crash salesViewController displays confirmViewController. When I press the back button in confirmViewContro

My app is crashing when I move between ViewControllers. This is the sequence that causes the crash salesViewController displays confirmViewController. When I press the back button in confirmViewController to go back to salesViewController, the application crashes.

I am not sure why. Here is the code for both of the controllers.

Thanks in advance.

#import "salesViewController.h"


@implementation salesViewController

@synthesize txtCardNumber;
@synthesize txtExpires;
@synthesize txtGrandTotal; 
@synthesize txtZip; 
@synthesize txtEmail;
@synthesize txtCCV2;
@synthesize txtInvoice;

//@synthesize button;

@synthesize strSaleType;



- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if(self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {



    }
    return self;
}

-(IBAction)btnTipCalculator:(id)sender
{
    NSLog(@"I was pressed");

    tipCalcViewController *tipVC = [[tipCalcViewController alloc] initWithNibName:@"tipCalcView" bundle:nil];
    tipVC.delegate = self;

    tipVC.passedTotal = txtGrandTotal.text;

    [self presentModalViewController:tipVC animated:YES];

    [tipVC release];    

}


-(IBAction)btnDateSelector:(id)sender
{
    NSLog(@"I was pressed");

    DatePickerViewController *datePickerViewController = [[DatePickerViewController alloc] initWithNibName:@"datePickerView" bundle:nil];
    datePickerViewController.delegate = self;

    [self presentModalViewController:datePickerViewController animated:YES];

    [datePickerViewController release]; 

}

-(void)datePickerViewController:(DatePickerViewController *)controller didChooseDate:(NSString *)chosenDate{


    NSLog(@"Chosen Date as String: %@", chosenDate );

    txtExpires.text = chosenDate;


    //do processing here... for example let's set the text of the button to the chosen date
    //[button setTitle: chosenDate forState: UIControlStateNormal];

    [self dismissModalViewControllerAnimated:YES];
}

//callback for modal tipCalculator
-(void)tipCalcViewController:(tipCalcViewController *)controller didChooseTip:(NSString *)chosenTip
{
    NSString *strNewTotal = chosenTip;

    //close tip calculator
    [self dismissModalViewControllerAnimated:YES];

    //update GUI
    txtGrandTotal.text = strNewTotal;


}


-(void)btnSubmitClicked
{
    NSURL *url = [NSURL URLWithString:@"https://www.eProcessingNetwork.Com/cgi-bin/tdbe/transact.pl"];
    //NSURL *url = [NSURL URLWithString:@"https://www.eprocessingnetwork.com/Reflect/Post.pl"];
    ASIFormDataRequest *request = [[[ASIFormDataRequest alloc] 
                                    initWithURL:url] autorelease];

    //get settings
    //NSUserDefaults *options = [NSUserDefaults standardUserDefaults];
    //NSString *acctNumber = [options stringForKey:@"accountNumber"];
    //NSString *restrictKey = [options stringForKey:@"restrictKey"];

    //uncomment for actual  
    //[request setPostValue:acctNumber forKey:@"ePNAccount"];
    //[request setPostValue:restrictKey forKey:@"RestrictKey"];


    if([strSaleType compare:@"Test"] == NSOrderedSame)
    {
        //FOR TESTING ONLY: UNCOMMENT ABOVE FOR ACTUAL ACCOUNT
        [request setPostValue:@"080880" forKey:@"ePNAccount"];
        [request setPostValue:@"yFqqXJh9Pqnugfr" forKey:@"RestrictKey"];

    }


    //FOR TESTING ONLY: UNCOMMENT ABOVE FOR ACTUAL ACCOUNT
    [request setPostValue:@"080880" forKey:@"ePNAccount"];
    [request setPostValue:@"yFqqXJh9Pqnugfr" forKey:@"RestrictKey"];


    //transaction type
    if([strSaleType compare:@"Sale"] == NSOrderedSame)
    {
        [request setPostValue:@"Sale"  forKey:@"TranType"];
    }

    if([strSaleType compare:@"Refund"] == NSOrderedSame)
    {
        [request setPostValue:@"Return"  forKey:@"TranType"];
    }
    if([strSaleType compare:@"Test"] == NSOrderedSame)
    {
        [request setPostValue:@"Sale"  forKey:@"TranType"];
    }

    //request no HTML output
    [request setPostValue:@"No"  forKey:@"HTML"];

    //needed to get transID for signature capture
    [request setPostValue:@"report"  forKey:@"Inv"];

    //card number
    [request setPostValue:txtCardNumber.text forKey:@"CardNo"];

    //parse date
    NSString *strDateFull = txtExpires.text;
    NSString *strMonth = [strDateFull substringWithRange: NSMakeRange(0, 2)];
    NSString *strYear =  [strDateFull substringWithRange: NSMakeRange(3, 2)];

    //expire month      
    [request setPostValue:strMonth forKey:@"ExpMonth"];

    //expire year
    [request setPostValue:strYear forKey:@"ExpYear"];

    //total, send as you would write it. no dollar sign needed
    [request setPostValue:txtGrandTotal.text forKey:@"Total"];

    //address - this makes TBDE ignore requests with no address
    [request setPostValue:@"1" forKey:@"SKIP_MISSING"];

    //zip
    [request setPostValue:txtZip.text forKey:@"Zip"];

    //ccv2
    [request setPostValue:@"CVV2Type" forKey:@"1"];
    [request setPostValue:txtCCV2.text forKey:@"123"];

    //email
    [request setPostValue:txtEmail.text forKey:@"EMail"];

    //invoice # - optional
    [request setPostValue:txtInvoice.text forKey:@"Invoice"];

    //blocking of course
    [request start];


    // get confirmation
    confirmViewController *anotherViewController = [[confirmViewController alloc] initWithNibName:@"confirmView" bundle:nil];

    //set properties
    anotherViewController.strConfirmation = [request responseString];
    anotherViewController.strCardNumber = txtCardNumber.text;
    anotherViewController.strExpires = txtExpires.text;
    anotherViewController.strAmount = txtGrandTotal.text;   

    [self.navigationController pushViewController:anotherViewController animated:YES];


    //reset interface
    if([anotherViewController.strApproval compare:@"""Y"] == NSOrderedSame)
    {
        txtCardNumber.text = @"";
        txtExpires.text = @"";
        txtGrandTotal.text = @"";
        txtZip.text = @"";
        txtCCV2.text = @"";
        txtEmail.text = @"";
        txtInvoice.text = @"";
    }

    [anotherViewController release];

/*  

    //display the results
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Info" 
                                                    message:[request responseString]
                                                   delegate:nil 
                                          cancelButtonTitle:@"OK" 
                                          otherButtonTitles: nil];
    [alert show];
    [alert release];    

*/  

}

/*
 // The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        // Custom initialization
    }
    return self;
}
*/

/*
开发者_高级运维// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    //Needed to get events
    [txtCardNumber setDelegate:self];
    [txtExpires setDelegate:self];
    [txtGrandTotal setDelegate:self];
    [txtZip setDelegate:self];
    [txtEmail setDelegate:self];
    [txtCCV2 setDelegate:self];
    [txtInvoice setDelegate:self];

    //adjust title depending on sale type
    if([strSaleType compare:@"Sale"] == NSOrderedSame)
    {
        self.title = @"Sales";
        NSLog(@"Passed in sale type: %@", strSaleType );    

    }
    if([strSaleType compare:@"Refund"] == NSOrderedSame)
    {
        self.title = @"Refunds";            
        NSLog(@"Passed here in sale type: %@", strSaleType );   

    }
    if([strSaleType compare:@"Test"] == NSOrderedSame)
    {
        self.title = @"Testing";            
        NSLog(@"Passed in sale type: %@", strSaleType );    

    }

    //add additional button
    UIBarButtonItem *submitButton = [[UIBarButtonItem alloc] initWithTitle:@"Submit" style:UIBarButtonItemStylePlain target:self action:@selector(btnSubmitClicked)];   
    self.navigationItem.rightBarButtonItem = submitButton;  
    [submitButton release]; 

}

- (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 {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void)dealloc {
    if(txtCardNumber != NULL)
    {   
        [txtCardNumber release];
    }

    if(txtExpires != NULL)
    {
        [txtExpires release];
    }

    if(txtGrandTotal != NULL)
    {
        [txtGrandTotal release];
    }

    if(txtZip != NULL)
    {
        [txtZip release];
    }

    if(txtEmail != NULL)
    {
        [txtEmail release];
    }

    if(txtCCV2 != NULL)
    {
        [txtCCV2 release];
    }

    if(txtInvoice != NULL)
    {
        [txtInvoice release];
    }

    if(strSaleType != NULL)
    {
        [strSaleType release];
    }


    [super dealloc];    
}


@end


#import "confirmViewController.h"


@implementation confirmViewController

@synthesize lblStatus;
@synthesize lblCardType;
@synthesize lblCardNumber;
@synthesize lblExpires;
@synthesize lblAmount;
@synthesize lblApproval;

@synthesize strConfirmation;
@synthesize strCardNumber;
@synthesize strExpires;
@synthesize strAmount;
@synthesize strApproval;


-(void)btnSignatureClicked
{
    sigCaptureViewController *anotherViewController = [[sigCaptureViewController alloc] initWithNibName:@"sigCaptureView" bundle:nil];
    [self.navigationController pushViewController:anotherViewController animated:YES];
    [anotherViewController release];

}

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    //prepare confirmation, all that is needed is the first string      
    NSArray *strings = [strConfirmation componentsSeparatedByString: @","]; 
    NSString *strPreParsed = [strings objectAtIndex:0];

    //break out yes/no so we can set status
    //NSString *strYesNO = [strPreParsed substringToIndex:2];
    NSString *strYesOrNo = [strPreParsed substringWithRange: NSMakeRange(1, 1)];

    //save approval for later
    strApproval = strYesOrNo;

    //debug
    NSLog(@"strNo= %@",strYesOrNo);
    NSLog(@"strPreParsed= %@", strPreParsed);

    //set results   
    if([strYesOrNo compare:@"Y"] == NSOrderedSame)
    {
        lblStatus.text = @"Approved";
        lblStatus.textColor = [UIColor greenColor];
    }

    if([strYesOrNo compare:@"N"] == NSOrderedSame)
    {
        lblStatus.text = @"Declined";
        lblStatus.textColor = [UIColor redColor];
    }

    if([strYesOrNo compare:@"U"] == NSOrderedSame)
    {
        lblStatus.text = @"Try Again";
        lblStatus.textColor = [UIColor redColor];
    }

    //set card type
    if([lblCardNumber.text compare:@"4"] == NSOrderedSame)
    {
        lblCardType.text = @"Visa";
    }

    if([lblCardNumber.text compare:@"5"] == NSOrderedSame)
    {
        lblCardType.text = @"Master";
    }

    if([lblCardNumber.text compare:@"6"] == NSOrderedSame)
    {
        lblCardType.text = @"Discover";
    }


    //set cardnumber
    lblCardNumber.text = strCardNumber;

    //set expires
    lblExpires.text = strExpires;

    //set amount
    lblAmount.text = strAmount;

    //set approval string
    lblApproval.text = strPreParsed;

    //add signature button
    UIBarButtonItem *signatureButton = [[UIBarButtonItem alloc] initWithTitle:@"Signature" style:UIBarButtonItemStylePlain target:self action:@selector(btnSignatureClicked)];  
    self.navigationItem.rightBarButtonItem = signatureButton;   
    [signatureButton release];

    //set title
    self.title = @"Approval";

}


- (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 {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;

}


- (void)dealloc {

    if(lblCardType != NULL)
    {
        [lblCardType release];
    }

    if(lblCardNumber != NULL)
    {
        [lblCardNumber release];
    }

    if(lblExpires != NULL)
    {
        [lblExpires release];
    }

    if(lblAmount != NULL)
    {
        [lblAmount release];
    }

    if(lblApproval != NULL)
    {
        [lblApproval release];
    }

    if(lblStatus != NULL)
    {
        [lblStatus release];
    }

    if(strConfirmation != NULL)
    {
        [strConfirmation release];
    }

    if(strCardNumber != NULL)
    {
        [strCardNumber release];
    }

    if(strExpires != NULL)
    {
        [strExpires release];
    }

    if(strAmount != NULL)
    {
        [strAmount release];
    }

    if(strApproval != NULL)
    {
        [strApproval release];
    }

    [super dealloc];


}


@end


I think you are releasing properties that should not be released, for instance you create strYesOrNo like this:

NSString *strYesOrNo = [strPreParsed substringWithRange: NSMakeRange(1, 1)];

without allocating the string. So the string belongs to the viewDidLoad function and will be released by this function. But after creating the strYesOrNo you assign it to a class property, like this:

strApproval = strYesOrNo;

By the time you dealloc your viewcontroller you try to release strApproval, but the viewDidLoad allready released this value and you get a bad-access. You can solve this problem by allocating the memory for strApproval like:

strApproval = [[NSString alloc] initWithString:strYesOrNo];

I did not go through all your code so maybe this is also true for some other properties. Hope this helped.

0

精彩评论

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